約700,000ファイルのディレクトリサイズ80GBで、ファイル名に英語以外の文字が含まれるファイル名がいくつかあります。面倒なファイルリストの検索以外にも、次のようなものがあります。
man ascii
の印刷可能な範囲にリストされていない文字(これらのファイルが識別されていることをテストできるため)?「foreign」が「ASCII文字ではない」という意味であると想定すると、パターンでfind
を使用して、名前に印刷可能なASCII文字を含まないすべてのファイルを検索できます。 :
_LC_ALL=C find . -name '*[! -~]*'
_
(スペースは http://www.asciitable.com/ にリストされている最初の印刷可能な文字です。_~
_が最後です。)
_LC_ALL=C
_のヒントが必要です(実際には、_LC_CTYPE=C
_および_LC_COLLATE=C
_)。それ以外の場合、文字範囲は正しく解釈されません。マニュアルページglob(7)
も参照してください。 _LC_ALL=C
_を使用すると、find
は文字列をASCIIとして解釈するため、マルチバイト文字(_π
_など)が疑問符として出力されます。これを修正するには、いくつかのプログラム(cat
など)にパイプするか、ファイルにリダイレクトします。
文字範囲を指定する代わりに、_[:print:]
_を使用して「印刷可能な文字」を選択することもできます。必ずCロケールを設定してください。そうしないと、かなり(一見)任意の動作が得られます。
例:
_$ touch $(printf '\u03c0') "$(printf 'x\ty')"
$ ls -F
dir/ foo foo.c xrestop-0.4/ xrestop-0.4.tar.gz π
$ find -name '*[! -~]*' # this is broken (LC_COLLATE=en_US.UTF-8)
./x?y
./dir
./π
... (a lot more)
./foo.c
$ LC_ALL=C find . -name '*[! -~]*'
./x?y
./??
$ LC_ALL=C find . -name '*[! -~]*' | cat
./x y
./π
$ LC_ALL=C find . -name '*[![:print:]]*' | cat
./x y
./π
_
tr -d '[\200-\377]'
を使用して各ファイル名を変換し、元の名前と比較すると、特殊文字が含まれるファイル名は同じになりません。
(上記は、ASCII以外の外国語を意味すると想定しています)
tr
を使用してファイル名からすべての外来文字を削除し、結果を元のファイル名と比較して、外来文字が含まれているかどうかを確認できます。
find . -type f > filenames
while read filename; do
stripped="$(printf '%s\n' "$filename" | tr -d -C '[[:alnum:]][[:space:]][[:punct:]]')"
test "$filename" = "$stripped" || printf '%s\n' "$filename";
done < filenames
受け入れられた回答 は役に立ちますが、ファイル名がすでにLANG
/LC_CTYPE
で指定されたエンコーディングになっている場合は、次のようにすることをお勧めします。
LC_COLLATE=C find . -name '*[! -~]*'
文字クラスはLC_CTYPE
の影響を受けますが、上記のコマンドは文字クラスを使用せず、範囲のみを使用するため、LC_CTYPE
は異常な文字が疑問符に置き換えられるのを防ぎます。