Mac OSXを実行していて、コマンドラインを使用して、同じ名前のファイルの数を見つけようとしています。
次のコマンドを使用しようとしました。
find ~ -type f -name "*" -print | basename | sort | uniq -d > duplicate_files
動かない!私が次のことをすると:
find ~ -type f -name "*" -print > duplicate_files
次に、duplicate_filesにはすべてのファイルのパスが含まれています。だから私は問題がbasename
にあると思います-標準入力を受け付けません。それから私は以下を試しました:
basename $(find ~ -type f -name "*" -print) > duplicate_files
しかし、それでもうまくいかないようです。インターネットでの検索はあまり喜びをもたらしていないようです。どんな考えでも大歓迎です。
basename
はコマンドライン引数で動作し、標準入力からは読み取りません。
basename
ユーティリティを呼び出す必要はありません。最後の/
の前の部分を削除するだけで、外部ユーティリティを呼び出すのに時間がかかります。各エントリのコマンドではなく、代わりにテキスト処理ユーティリティを使用できます。
find ~ -type f | sed 's!.*/!!' | sort | uniq -d
ファイルの場所を追跡する方が便利な場合があります。名前で並べ替えると、重複を見つけやすくなりますが、sort
には最後のフィールドを使用するオプションがありません。できることは、最後の/
で区切られたフィールドを先頭にコピーし、並べ替えてから、アドホックawk処理を使用して重複を抽出して表示することです。
find ~ -type f |
sed 's!.*/\(.*\)!\1/&!' | # copy the last field to the beginning
sort -t/ -k1,1 |
cut -d/ -f2- | # remove the extra first field (could be combined with awk below)
awk -F / '{
if ($NF == name) {
if (previous != "") {print previous; previous = ""}
print
} else {
previous = $0
name = $NF
}
'
(私はあなたのファイル名のどれも改行文字を含まないと仮定していることに注意してください。)
組み込みのfind
機能を使用してファイル名だけを出力しないのはなぜですか。
find ~ -type f -printf '%f\n' | sort | uniq -c
(GNU find
)または少なくとも次のようなものを想定:
find ~ -exec basename {} \; | sort | uniq -c
basename
は、パイプ経由で読み取ることも、複数のファイルを一度に処理することもできません。
ps。すべてのファイルを一覧表示する場合は、-name '*'
を指定する必要はありません。これはデフォルトのオプションです。
これは私にとってOSXではうまくいくようです:
find ~ -type f -exec basename -a {} + | sort | uniq -d
代替案(ファイル名に改行がないと想定):
find ~ -type f | awk -F/ '{print $NF}' | sort | uniq -d
次のように、xargs
をbasename
とともに使用して、目的の出力を取得できます。
find ~ -type f -name "*" -print | xargs -l basename | sort | uniq -d > duplicate_files
連想配列を処理するbash
の最近のバージョンでは、以下はさらに、改行が埋め込まれたパス名を処理します。
#!/bin/bash
topdir=$HOME
shopt -s globstar # enable the ** glob
declare -A count
# count the number of times each filename (base name) occurs
for pathname in "$topdir"/**; do
# skip names that are not regular files (or not symbolic links to such files)
[ ! -f "$pathname" ] && continue
# get the base name
filename=${pathname##*/}
# add one to this base name's count
count[$filename]=$(( ${count[$filename]} + 1 ))
done
# go through the collected names and print any name that
# has a count greater than one
for filename in "${!count[@]}"; do
if [ "${count[$filename]}" -gt 1 ]; then
printf 'Duplicate filename: %s\n' "$filename"
fi
done
これは外部ユーティリティを使用しません。