web-dev-qa-db-ja.com

ファイル名に非ASCIIまたは印刷不可能な文字が含まれるファイルを特定する

約700,000ファイルのディレクトリサイズ80GBで、ファイル名に英語以外の文字が含まれるファイル名がいくつかあります。面倒なファイルリストの検索以外にも、次のようなものがあります。

  • これらのファイル名を一覧表示したり、別の方法で識別したりする簡単な方法はありますか?
  • 印刷可能な英語以外の文字を生成する方法-man asciiの印刷可能な範囲にリストされていない文字(これらのファイルが識別されていることをテストできるため)?
26
suspectus

「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
./π
_
36
Lekensteyn

tr -d '[\200-\377]'を使用して各ファイル名を変換し、元の名前と比較すると、特殊文字が含まれるファイル名は同じになりません。

(上記は、ASCII以外の外国語を意味すると想定しています)

6
Timo

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
3
Ernest A

受け入れられた回答 は役に立ちますが、ファイル名がすでにLANG/LC_CTYPEで指定されたエンコーディングになっている場合は、次のようにすることをお勧めします。

LC_COLLATE=C find . -name '*[! -~]*'

文字クラスはLC_CTYPEの影響を受けますが、上記のコマンドは文字クラスを使用せず、範囲のみを使用するため、LC_CTYPEは異常な文字が疑問符に置き換えられるのを防ぎます。

0
SamB