web-dev-qa-db-ja.com

findまたはgrepを使用して、異なるエンコーディングシステム(WindowsからLinux)のアクセント付き文字を含むファイル名を検索します

私はstackoverflowで私のような質問に遅れてタグを付けようとしました( Linuxファイルシステムで非UTF8ファイル名を検索 )、これまでのところ運がないので、さらに返信を引き出すために、ここでもう一度行きます...

上記のリンクのOPと同じ問題があり、convmvは自分のファイルシステムを修正するための優れたツールです。したがって、私の質問は学術的ですが、「find」が非標準のASCII文字を見つけることができないのは不十分です(実際には信じられません)。

ユニコードFSのように見えるもので非標準文字を含むファイル名を見つけるために使用するオプションの組み合わせを知っている人はいますか?私の場合、文字はユニコードではなく8ビット拡張ASCIIのようです、ファイルはWindowsマシン(iso-8859-1)と私は定期的にそれらをフェッチする必要があります。 findやgrepがconvmvと同じように実行できる方法を確認したいと思います。

サンプルファイル:

_> ls
Abc�def ÉÈéèáà-rest everest éverest

> ls -b
Abc\251def  ÉÈéèáà-rest  everest  éverest
_

最初のファイルはWindowsからのものです(またはtouch $(printf "Abc\xA9def")でシミュレートされます)。

_> find . -regex '.*[^a-zA-Z./].*'
./ÉÈéèáà-rest

> ls | egrep '[^a-zA-Z]'
ÉÈéèáà-rest
_

それらのほとんどすべてが欠落しています(ハイフンでそのファイルが保存され、色付きのgrepで確認できます)。ここで起こっていることは、私が期待することではありません。findもgrepも、提供された範囲外であるとしてアクセント付き文字を受け取ることはできません[^ a-zA-Z。/]。

_> find . -regex '.*é.*'
./éverest
./ÉÈéèáà-rest

> ls | egrep 'é'
ÉÈéèáà-rest
éverest

> ls | egrep '[é]'
ÉÈéèáà-rest
éverest

> find . -regex '.*[é].*'
./éverest
./ÉÈéèáà-rest
_

奇妙なことに、両方が提供されたときに標準のアクセントを拾うことができます(範囲内を含む)。\xA9、\ 0251、または\ o251を使用したfindまたはgrepの試行は失敗します(一致しません)。

_> ls | fgrep e
Abc�def
ÉÈéèáà-rest
everest
éverest
_

物議を醸していない文字を探すと、予想どおり、grepを含むすべてのファイルが表示されます。

_> find . -regex '.*e.*'
./éverest
./ÉÈéèáà-rest
./everest

> find . -name '*e*'
./éverest
./ÉÈéèáà-rest
./everest
_

ただし、findは非常に差別的です。通常の文字を検索しても、ファイルシステムの名前エンコーディングスキーマで受け入れ可能な文字の範囲外の文字を含むファイル名が削除されるように思われます。

ファイルがファイルシステムにあるかどうかに関する限り、findはそれを見つける必要がありますよね?しかし、私が知らない機能があるかもしれませんか?

どんな洞察も大歓迎です。

5
asoundmove

GNUツールには、文字エンコードでサポートされている場合、正規表現文字クラスと一致するときにアクセント付き文字がベース文字のように扱われるようにするコードがあるようです。これは、「正規表現の記述を容易にする一種の機能ですが、この場合は邪魔になります。

「検索」コマンドラインに次の変更を加えてみてください。

LANG=C find . -regex '.*[^a-zA-Z./].*'

これにより、「find」コマンドのコンテキストでのみLANG環境変数が設定されます。 「C」言語エンコーディングはASCIIのみをサポートしているため、アクセント付き文字はベース文字として扱われなくなり、正規表現によって適切に照合されます。

8
Jander

ジャンダーの答えは完璧に機能します。これをさらに活用したい人のために、もう1つのヒントを紹介します。

LANG = Cの場合、findは、疑問符付きの非ASCII文字を表示します。それをそのファイルシステムで通常の表示に戻すには、出力をcatにパイプするだけです。

LANG=C find . -regex '.*[^a-zA-Z./-].*'
./??verest
./????????????-rest
./Abc?def

LANG=C find . -regex '.*[^a-zA-Z./-].*' | cat
./éverest
./ÉÈéèáà-rest
./Abc�def
5
asoundmove
find . | grep -E '.*[^[:print:]].*'

すべてのposix文字クラスのリストについては、以下を参照してください。 http://www.regular-expressions.info/posixbrackets.html

0
Tom Hale