labunix's blog

labunixのラボUnix

第9回寒中シェル芸勉強会を解いてみた。

■第9回寒中シェル芸勉強会を解いてみた。

 シェル芸勉強会スライド一覧
 http://blog.ueda.asia/?page_id=6841問

 まず、次のようにファイルを作ってください。

 $ touch apple avocado banana cinnamon melon
 $ ls
 apple  avocado  banana  cinnamon  melon

 「a,b,c,m」というディレクトリを作って、1文字目が対応するファイルを
 それぞれのディレクトリに移動してください。

■普通に解く。

$ mkdir {a,b,c,m} ; \
  find . -type f | awk '{print "mv",$1,$1}' | sed s%./%%g | \
  sed s/" \([a-z]\)[a-z]*\$"/" \1"/ | sh

$ tree
.
├── a
│   ├── apple
│   └── avocado
├── b
│   └── banana
├── c
│   └── cinnamon
└── m
    └── melon

4 directories, 5 files

第2問

 まず、次のように名前にスペースが入ったファイルを作ります。

 $ touch "私は " "オシャレな " "足が 10"
 $ ls -l
 total 0
 -rw-r--r-- 1 ueda staff 0  2 14 11:22 私は 蟹
 -rw-r--r-- 1 ueda staff 0  2 14 11:22 足が 10本
 -rw-r--r-- 1 ueda staff 0  2 14 11:22 オシャレな 蟹

 このままでは何かと扱いづらいので、間にアンダーバーを入れて
 次のように名前を変更してください。

 $ ls -l
 total 0
 -rw-r--r-- 1 ueda staff 0  2 14 11:25 私は_蟹
 -rw-r--r-- 1 ueda staff 0  2 14 11:25 足が_10本
 -rw-r--r-- 1 ueda staff 0  2 14 11:25 オシャレな_蟹

■ノーマルな手段で。

$ touch "私は " "オシャレな " "足が 10"; \
  ls -l *" "* | cut -c 47- | grep -v ^\$ | \
  while read line;do \
    mv "$line" "`echo "$line" | sed s/" "/"_"/g`"; \
  done3問

 ディレクトリを適当に作って、20140101から20141231まで、
 日付に対応したファイルを作って下さい。

 各ファイルの中には各日付に対応するdateコマンドの出力を書き込んで下さい。

■12度やるか、変数に入れるか。それが問題だ。

$ test -d daylist || mkdir daylist && cd daylist; \
  seq 20140101 20141231 | \
  for n in `xargs`;do \
    date -d "$n" > /dev/null 2>&1 &&  date -d "$n" | tee $n >/dev/null 2>&1; \
  done

$ ls | wc -l
365

$ grep . 2014* | head -5
20140101:201411日 水曜日 00:00:00 JST
20140102:201412日 木曜日 00:00:00 JST
20140103:201413日 金曜日 00:00:00 JST
20140104:201414日 土曜日 00:00:00 JST
20140105:201415日 日曜日 00:00:00 JST

第4問

 次のように4個ファイルを作って、a_ramenとa_curry、b_appleとb_tomatoの
 ファイルの中身を入れ替えてください。

 $ echo カレー > a_ramen
 $ echo ラーメン > a_curry
 $ echo トマト > b_apple
 $ echo リンゴ > b_tomato

■面倒の一言。

$ grep . [ab]*
a_curry:ラーメン
a_ramen:カレー
b_apple:トマト
b_tomato:リンゴ

$ grep . [ab]* | tr "\n\|:" " " | \
  awk '{;print $4,$1"\n"$2,$3"\n"$8,$5"\n"$6,$7}' | \
  sed s/" "/" > "/g | sed s/^/"echo "/g | sh

$ grep . [ab]*
a_curry:カレー
a_ramen:ラーメン
b_apple:リンゴ
b_tomato:トマト

第4問

 各月ごとにtar.gzファイルにしてください。

$ ls *[0-9] | cut -c 1-6 | sort -u | \
  for list in `xargs`;do tar zcvf ${list}.tar.gz $list*;done
$ for list in *.tar.gz;do tar ztvf $list;done | awk '{print $NF}' | wc -l
3656問

 次のようなディレクトリ・ファイルを作って下さい。
 ~/a/a/a/.../a/a/b (aが百個、bはファイル)

■作成ついでにシェル芸で確認

$ for n in `seq 1 100`;do echo -n "a/";done | \
  awk '{print "mkdir -p",$1,"\ntouch",$1"b"}' | sh

$ find . -type f -name b | tr '/' '\n' | grep a | wc -l
1007問

 先ほど作ったファイルbを、50番目のaディレクトリに移動して下さい。

■上に同じ。

$ find . -type f -name b | \
  echo "mv `xargs` $(for n in `seq 1 50`;do echo -n "a/";done)" | sh
$ find . -type f -name b | tr '/' '\n' | grep a | wc -l
508問

 先ほど作ったディレクトリについて rm -r を使わずに~/a 以下のディレクトリを消去してください。

■「~/」はホームディレクトリなので、「./」カレントディレクトリに読み替えて作業する。
 「cd」しすぎて大事な空の「a」ディレクトリを消してしまわないようにw。

$ find . -type f -name "b" -exec rm {} \;; \
  for n in `seq 1 100`;do cd a;done;for n in `seq 1 99`;do cd ../;rmdir a;done