リストに重複したファイル名をリストしたいですか?

リストに重複したファイル名をリストしたいですか?
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これを行うべきではないいくつかの理由は次のとおりです。

答え3

これユニークユーティリティは重複エントリを削除または一覧表示します。入力は次のようにする必要があります。ソート済み。ファイル名部分のみが関連付けられているため、ファイル名の左側にある内容を無視するようにこれらのユーティリティに指示します。

sort -k 1.54 f.txt | uniq -s 54 -cd

関連情報