bash-3.00$ cat f.txt
-rw-r--r-- 1 mukesh other 102 Nov 5 18:32 f1.txt
-rw-r--r-- 1 mukesh other 19 Nov 5 18:32 f2.txt
-rw-r--r-- 1 mukesh other 204 Nov 5 18:32 f3.txt //DUPLICATE
-rw-r--r-- 1 mukesh other 204 Nov 6 18:32 f3.txt //DUPLICATE
-rw-r--r-- 1 mukesh other 204 Nov 6 18:32 f100.txt
f.txt というファイルに上記のファイル名がリストされているとします。重複したファイル名をすべてリストしたいです(ファイル名のみ)、重複したファイル名と重複した数を表示します。
例:上記のリストにはf3.txtの重複があり、合計2つのf3.txtファイル名が見つかりました。
答え1
述べたように、awk
解決策は次のとおりです。
awk '{d[$9]++}END{for(f in d)if(d[f]>1)print d[f],f}' f.txt
名前にスペース文字を含むファイルもある場合は、いくつかの回避策が必要です。
awk '{f=$9;for(i=10;i<=NF;i++)f=f" "$i;d[f]++}END{for(f in d)if(d[f]>1)print d[f],f}' f.txt
たとえば、シンボリックリンクを処理すると、上記の回避策が失敗する可能性があります。結局のところ、ls
出力を解析するのは良い考えではありません。可能であれば、別の方法でf.txtを生成することをお勧めします。 (たとえば、find
リストstat
形式をより細かく制御できます。)
答え2
bash
あなたの質問にbash 3を使用できることが明確に示されているので、これは純粋な解決策です。
#!/bin/bash
if [[ -t 0 ]]; then
printf '%s\n' 'No input!'
exit 1
fi
while read -ra _file; do
_file="${foo[*]:8}"
for _file_name_already_known in "${_files[@]}"; do
if [[ ${_file_name_already_known} == "${_file}" ]]; then
for _file_name_already_printed in "${_already_printed[@]}"; do
[[ ${_file_name_already_printed} == "${_file}" ]] && continue 3
done
printf '%s\n' "${_file}"
_already_printed+=( "${_file}" )
fi
done
_files+=( "${_file}" )
done
出力:
$ ./lsdups < f.txt
f3.txt
./lsdups < file
.
ls
ただし、出力が最善の選択ではないことに注意してください。http://mywiki.wooledge.org/ParsingLsこれを行うべきではないいくつかの理由は次のとおりです。