回答:
GNUユーティリティ(または少なくともゼロで終了する行を処理できるセット)を使用できる場合、別の答えには素晴らしい方法があります。
find . -maxdepth 1 -print0 | sort -z | uniq -diz
注:出力には、ゼロで終了する文字列が含まれます。それをさらに処理するために使用するツールは、それを処理できるはずです。
ゼロで終了する行を処理するツールがない場合、またはそのようなツールが利用できない環境でコードが機能することを確認したい場合は、小さなスクリプトが必要です。
#!/bin/sh
for f in *; do
find . -maxdepth 1 -iname ./"$f" -exec echo \; | wc -l | while read count; do
[ $count -gt 1 ] && echo $f
done
done
この狂気とは何ですか?これをクレイジーなファイル名に対して安全にするテクニックの説明については、この回答を参照してください。
-mindepth
ですか?
find
。回答を編集して、GNU以外のソリューションを含めました。
上記には多くの複雑な答えがありますが、これはそれらのすべてよりも簡単で速いようです:
find . -maxdepth 1 | sort -f | uniq -di
サブディレクトリで重複するファイル名を検索する場合は、パス全体ではなくファイル名のみを比較する必要があります。
find . -maxdepth 2 -printf "%f\n" | sort -f | uniq -di
編集:ショーンJ.ゴフは、改行文字を含むファイル名があると失敗することを指摘しました。GNUユーティリティを使用している場合は、これらも機能させることができます。
find . -maxdepth 1 -print0 | sort -fz | uniq -diz
-print0
(検索用)及び-z
(ソートとuniqのための)オプションそれらの原因NULで終了する文字列の代わりに、改行文字で終了する文字列での作業に。ファイル名にはNULを含めることができないため、これはすべてのファイル名に対して機能します。
大文字と小文字を区別しない方法でファイル名のリストをソートし、重複を印刷します。sort
大文字と小文字を区別しないソートのオプションがあります。GNUもそうですがuniq
、他の実装はそうでuniq
はありません。あなたができることは、最初に遭遇したものを除いて、重複のセットのすべての要素を出力することだけです。GNUツールでは、ファイル名に改行が含まれないと仮定すると、重複セットごとに1つを除くすべての要素を印刷する簡単な方法があります。
for x in *; do printf "%s\n" "$x"; done |
sort -f |
uniq -id
移植性のある方法として、ファイル名に改行が含まれていないと仮定して、複製の各セット内のすべての要素を印刷します。
for x in *; do printf "%s\n" "$x"; done |
sort -f |
awk '
tolower($0) == tolower(prev) {
print prev;
while (tolower($0) == tolower(prev)) {print; getline}
}
1 { prev = $0 }'
改行を含むファイル名に対応する必要がある場合は、PerlまたはPythonを使用してください。以下のサンプルコードでは改行を使用して独自の出力で名前を分離しているため、出力を微調整するか、同じ言語でさらに処理する必要があることに注意してください。
perl -e '
foreach (glob("*")) {push @{$f{lc($_)}}, $_}
foreach (keys %f) {@names = @{$f{$_}}; if (@names > 1) {print "$_\n" foreach @names}}
'
これが純粋なzshソリューションです。重複した要素を配列またはグロブの結果に保持する組み込みの方法がないため、少し冗長です。
a=(*)(N); a=("${(@io)a}")
[[ $#a -le 1 ]] ||
for i in {2..$#a}; do
if [[ ${(L)a[$i]} == ${(L)a[$((i-1))]} ]]; then
[[ ${(L)a[$i-2]} == ${(L)a[$((i-1))]} ]] || print -r $a[$((i-1))]
print -r $a[$i]
fi
done
GNUなしfind
:
LANG=en_US ls | tr '[A-Z]' '[a-z]' | uniq -c | awk '$1 >= 2 {print $2}'
uniq
は、大文字と小文字を区別しないフラグiがあります。
最終的にこの方法で管理しました。
find . | tr '[:upper:]' '[:lower:]' | sort | uniq -d
find
代わりにls
フルパス(多くのサブディレクトリ)が必要だったので使用しました。私はこれを行う方法を見つけられませんでしたls
。
sort
、uniq
それぞれ大文字と小文字を区別しないフラグfとiがあります。
その後、ファイルの1つなどの名前を変更したい場合:
find . -maxdepth 1 | sort -f | uniq -di | while read f; do echo mv "$f" "${f/.txt/_.txt}"; done