やりたいこと:
次のような二つのディレクトリがあり、同じ名前のファイルがそれぞれあるが、その内サイズが異なるファイル名を表示する。
これをワンライナーで実現する。
$ ls -l * TEST_1: total 32 -rw-r--r-- 1 estis estis 4 4 7 09:44 test01 -rw-r--r-- 1 estis estis 44 4 7 09:49 test02 -rw-r--r-- 1 estis estis 118 4 7 09:46 test03 -rw-r--r-- 1 estis estis 40 4 7 09:47 test04 TEST_2: total 32 -rw-r--r-- 1 estis estis 4 4 7 09:44 test01 -rw-r--r-- 1 estis estis 4 4 7 09:45 test02 -rw-r--r-- 1 estis estis 118 4 7 09:46 test03 -rw-r--r-- 1 estis estis 80 4 7 09:48 test04
こういう状態なので、欲しい答えは、
test02とtest04。
(1) awkを使ってみた。
$ ls -l * |awk '{if(NF > 2) print $9,$5}'| sort | awk '{if(x != $1){x = $1; y = $2}else if(y != $2) print $1}' test02 test04
(2) perlを使ってみた。
$ ls -l *|perl -wnla -e '$filesize{$F[8]}{$F[4]} = 1 if(@F > 2);END{ for(keys %filesize){ print $_ if(scalar keys %{$filesize{$_}} != 1)}}' test02 test04
どちらも同じように答えるが、ここでディレクトリをもう一つ増やしてこんな感じにしてみた。
$ ls -l * TEST_1: total 32 -rw-r--r-- 1 estis estis 4 4 7 09:44 test01 -rw-r--r-- 1 estis estis 44 4 7 09:49 test02 -rw-r--r-- 1 estis estis 118 4 7 09:46 test03 -rw-r--r-- 1 estis estis 40 4 7 09:47 test04 TEST_2: total 32 -rw-r--r-- 1 estis estis 4 4 7 09:44 test01 -rw-r--r-- 1 estis estis 4 4 7 09:45 test02 -rw-r--r-- 1 estis estis 118 4 7 09:46 test03 -rw-r--r-- 1 estis estis 80 4 7 09:48 test04 TEST_3: total 32 -rw-r--r-- 1 estis estis 4 4 7 16:15 test01 -rw-r--r-- 1 estis estis 57 4 7 16:21 test02 -rw-r--r-- 1 estis estis 118 4 7 16:15 test03 -rw-r--r-- 1 estis estis 40 4 7 16:15 test04 -rw-r--r-- 1 estis estis 0 4 7 16:18 test05
test05というファイルがTEST_3ディレクトリにしか存在しない。
test02ファイルは3ファイル全てサイズが異なる。
ここで欲しい答えは、
test02とtest04とtest05、TEST_3ディレクトリ以外のtest05ファイルのサイズはundefという解釈で。
さて、さっきのコマンドを実行してみると
(1)
$ ls -l * |awk '{if(NF > 2) print $9,$5}'| sort | awk '{if(x != $1){x = $1; y = $2}else if(y != $2) print $1}' test02 test02 test04
(2)
$ ls -l *|perl -wnla -e '$filesize{$F[8]}{$F[4]} = 1 if(@F > 2);END{ for(keys %filesize){ print $_ if(scalar keys %{$filesize{$_}} != 1)}}' test02 test04
という結果になり、満足できない。
(3) awkを使う方法でコマンドを修正。
$ ls -l * |awk '{if(NF > 2) filesize[$5" "$9]++}END{for(i in filesize){if (filesize[i] == 1) print i}}'|awk '{file[$2]}END{for( i in file)print i}' test02 test04 test05
(4) perl版を一工夫してみた。
$ ls -l *|perl -wnla -e '$filesize{$F[8]}{$F[4]}++ if @F > 2;END{ for(keys %filesize){ $file = $_; for(keys %{$filesize{$file}}){ print $file if($filesize{$file}{$_} == 1)}}}' test02 test02 test02 test05 test04
これだと間違いではないが冗長。なので、
(4')
$ ls -l *|perl -wnla -e '$filesize{$F[8]}{$F[4]}++ if @F > 2;END{ for(keys %filesize){ $file = $_; for(keys %{$filesize{$file}}){ print $file if($filesize{$file}{$_} == 1)}}}'|uniq test02 test05 test04
uniqに頼った。
(5) いやいや、やっぱりperlだけで何とかするんだ〜!
$ ls -l *|perl -wnla -e '$filesize{$F[8]}{$F[4]}++ if (@F > 2);END{ for(keys %filesize){ $file = $_; for(keys %{$filesize{$file}}){ $filename{$file}++ if($filesize{$file}{$_} == 1)}} print join "\n", keys %filename}' test02 test04 test05
できた。