■「第13回危険でない方のシェル芸勉強会」を解いてみた。 【問題と解答例】第13回危険でない方のシェル芸勉強会 http://blog.ueda.asia/?p=3792 ■過去14回分が下記にあります。 シェル芸勉強会スライド一覧 http://blog.ueda.asia/?page_id=684 $ w3m -dump "http://blog.ueda.asia/?page_id=684" | \ grep "^第[0-9]*回\|^番外編" | \ awk '{print};END{print "全"NR"回"}' 第13回 第12回 第11回 第10回 第9回 第8回 第7回 第6回 in LLまつり 第5回 第4回 番外編(OSC 2013 Tokyo/Spring) 第3回 第2回 第1回 全14回 ■私も暇なのか、結構解いてます。。。 第12回本当は怖くないシェル芸勉強会」を解いてみた http://labunix.hateblo.jp/entry/20140803/1407076184 ※第11回 jus & USP友の会共催 シェルワンライナー勉強会@関西(第11回シェル芸勉強会)」を解いてみた。 http://labunix.hateblo.jp/entry/20140616/1402927517 第10回シェル芸勉強会」を解いてみた。 http://labunix.hateblo.jp/entry/20140930/1412085463 ※第6回 「LLまつりでシェル芸人をジェネレートしてきた」を参加していないのに解いてみた。 http://labunix.hateblo.jp/entry/20130915/1379249444 ※第4回 4月13日、渋谷でシェル芸勉強会に参加していないのに解いてみた。 http://d.hatena.ne.jp/labunix/20130414 ※第4回 勝手に予習編 USP友の会「4月13日、渋谷でシェル芸勉強会」の予習をしたい方向け http://d.hatena.ne.jp/labunix/20130325 ※第3回 「シェル芸爆破デスマッチ勉強会」に参加してないのに解いてみた http://d.hatena.ne.jp/labunix/20130217 第2回チキチキ! シェル芸人養成勉強会 参加報告 http://d.hatena.ne.jp/labunix/20121209 ※第1回 USP友の会会長が出題した前半戦を解いてみた。 http://d.hatena.ne.jp/labunix/20121111 USP友の会会長が出題した後半戦を解いてみた。 http://d.hatena.ne.jp/labunix/20121112 ■それでは始めましょう。 Q1. 次のようにShift JISのファイルを作り、 Shift JISで「きく」と書いてあるファイルを探すワンライナーを考えてください。 (答えは「b」ですね。) $ echo あいうえお | nkf -xLws > a $ echo かきくけこ | nkf -xLws > b $ echo さしすせそ | nkf -xLws > c ■ファイル名を一緒に出してしまえば簡単。 $ grep . [abc] | nkf -Lw | grep きく | awk -F\: '{print $1}' b Q2. 次のようにディレクトリa,b,c,dに1,2,…,9というファイルがあります。 各ディレクトリ内のファイル数をワンライナーで数えてください。 ■まずはtree構造を作るところから。 $ mkdir {a,b,c,d}; \ touch a/{1,2,3} b/{4,5} d/{6,7,8,9} $ tree . ├── a │ ├── 1 │ ├── 2 │ └── 3 ├── b │ ├── 4 │ └── 5 ├── c └── d ├── 6 ├── 7 ├── 8 └── 9 4 directories, 9 files $ find . -type f | awk -F\/ '{print $2}' | uniq -c 4 d 2 b 3 a ■解答例と同じだったので、findもlsも使わないパターン。。。 $ echo */* | sed s/" \|\/[0-9]"/"\n"/g | grep -v "^\$" | sort | uniq -c 3 a 2 b 4 d Q3.今度は次のような配置でファイル1,2,…,9が置かれているときに、 ワンライナーでa、cの下のファイルの総数をカウントしてください (ディレクトリを除く)。つまりaなら5個、cなら4個が正解です。 ■これも作るところから。 $ mkdir -p a/b c/d; \ touch a/{1,2,3} a/b/{4,5} c/d/{6,7,8,9}; \ tree . ├── a │ ├── 1 │ ├── 2 │ ├── 3 │ └── b │ ├── 4 │ └── 5 └── c └── d ├── 6 ├── 7 ├── 8 └── 9 4 directories, 9 files $ find . -type f | cut -c 3-3 | uniq -c 5 a 4 c Q4.まず、次のように8桁日付のファイルを作ります。 $ seq -w 1 31 | xargs -I@ touch 201401@ $ ls | column -c 80 20140101 20140108 20140115 20140122 20140129 20140102 20140109 20140116 20140123 20140130 20140103 20140110 20140117 20140124 20140131 20140104 20140111 20140118 20140125 20140105 20140112 20140119 20140126 20140106 20140113 20140120 20140127 20140107 20140114 20140121 20140128 曜日別にディレクトリを作り、その中に当該するファイルを放り込んでください。 ■英語パターンで。 $ for list in 2*;do \ TARGET=`env LANG=C date -d "$list" '+%a'`; \ test -d "$TARGET" || mkdir "$TARGET"; \ mv "$list" "$TARGET"; \ done $ tree . ├── Fri │ ├── 20140103 │ ├── 20140110 │ ├── 20140117 │ ├── 20140124 │ └── 20140131 ├── Mon │ ├── 20140106 │ ├── 20140113 │ ├── 20140120 │ └── 20140127 ├── Sat │ ├── 20140104 │ ├── 20140111 │ ├── 20140118 │ └── 20140125 ├── Sun │ ├── 20140105 │ ├── 20140112 │ ├── 20140119 │ └── 20140126 ├── Thu │ ├── 20140102 │ ├── 20140109 │ ├── 20140116 │ ├── 20140123 │ └── 20140130 ├── Tue │ ├── 20140107 │ ├── 20140114 │ ├── 20140121 │ └── 20140128 └── Wed ├── 20140101 ├── 20140108 ├── 20140115 ├── 20140122 └── 20140129 7 directories, 31 files Q5.以下のようにa,b,cというディレクトリを作り、その下に「{a,b,c}数字」という ファイルを作ります。ファイル名の1文字目とディレクトリ名が一致するように ファイルを移動してください。 ■これもつくるところから。 $ mkdir {a,b,c}; \ touch a/{a01,b01} b/{a02,a03,c01} c/a04; \ tree . ├── a │ ├── a01 │ └── b01 ├── b │ ├── a02 │ ├── a03 │ └── c01 └── c └── a04 $ for n in a b c;do mv */${n}[0-9]* ${n};done mv: 'a/a01' と 'a/a01' は同じファイルです $ tree . ├── a │ ├── a01 │ ├── a02 │ ├── a03 │ └── a04 ├── b │ └── b01 └── c └── c01 3 directories, 6 files Q6.次のようにディレクトリa, b, cの下に、8桁日付のファイルをいくつか置きます。 各ディレクトリの最新日付のファイルをカレントディレクトリ (a,b,cのあるディレクトリ)にコピーしてください。 各ディレクトリの最新ファイルの日付はそれぞれ違い、コピーの際に衝突しない こととします。 ■今回はつくるのが多いですね。。。 $ mkdir {a,b,c}; \ touch a/{20130120,20140901,20141021} \ b/{20131011,20140202} \ c/{20110202,20130224,20141224} $ tree . ├── a │ ├── 20130120 │ ├── 20140901 │ └── 20141021 ├── b │ ├── 20131011 │ └── 20140202 └── c ├── 20110202 ├── 20130224 └── 20141224 3 directories, 8 files $ for n in a b c;do cp "${n}/`ls -na $n | tail -1 | awk '{print $NF}'`" .;done $ tree . ├── 20140202 ├── 20141021 ├── 20141224 ├── a │ ├── 20130120 │ ├── 20140901 │ └── 20141021 ├── b │ ├── 20131011 │ └── 20140202 └── c ├── 20110202 ├── 20130224 └── 20141224 3 directories, 11 files Q7.Q6について、適当にファイルをtouchします。今度はタイムスタンプが最新の ファイルを、a, b, cそれぞれからカレントディレクトリにコピーしてください。 コピーの際にタイムスタンプを変えない事。 $ touch a/2013* c/2011* $ find . -type f -mtime -0.002 -exec cp -p {} . \; $ ls -l 201[13]* [ac]/{20110202,20130120} | awk '{print $(NF-1),$NF}' 01:04 20110202 01:04 20130120 01:04 a/20130120 01:04 c/20110202 Q8.次のように5個ファイルを作ります。file1をfile2, file2をfile3, file3をfile4, file4をfile5, file5をfile1にmvしてください。 $ for i in 1 2 3 4 5 ; do echo $i > file$i ; done $ grep . file* file1:1 file2:2 file3:3 file4:4 file5:5 ■難しく考えない方が良い。 $ for n in `seq 5 -1 1`;do mv "file$n" "file$(($n+1))";done;mv file6 file1 $ grep . file* file1:5 file2:1 file3:2 file4:3 file5:4