ファイル名がUTF-8のファイルシステムにファイル名エラーがあります。 zsh:、Latin 1D�sinstaller
による実際の名前は、「削除」を意味する野蛮なフランス語です。 Zshはこれを一致させませんが、ワイルドカードと一致させます。これは私が期待する動作です。D$'\351'sinstaller
Désinstaller
[[ $file =~ '^.*$' ]]
*
今私はまだ実行時にそれを見つけることを期待していますfind . -name '*'
。実際、ファイル名がこのテストに失敗するとは決して予想しません。ただし、ファイルのLANG=en_US.utf8
場合いいえLANG=C
が表示されたら(またはen_US
、または)を設定する必要があり''
ます。
質問: その後の実装は何ですか?結果をどのように予測しますか?
情報: Arch Linux 3.14.37-1-lts, find(GNU findutils) 4.4.2
答え1
本当に良いボーナスですね。 GNU findのソースコードを少し見てみると、これはfnmatch
無効なバイトシーケンス(pred_name_common
in pred.c
)の動作方法で帰結すると言いたいと思います。
b = fnmatch (str, base, flags) == 0;
(...)
return b;
このコードはfnmatch
戻り値が0かどうかをテストしますが、エラーをチェックしません。これにより、エラーが「一致しない」と報告されます。
何年も前に、*
破損したファイル名でもパターンに対して常にtrueを返すようにこのlibc関数の動作を変更することが提案されましたが、私が知っている限り、このアイデアは拒否されました(参照:https://sourceware.org/ml/libc-hacker/2002-11/msg00071.html):
fnmatchが無効なマルチバイト文字を検出した場合は、「*」がその文字列と一致するようにシングルバイト一致で置き換える必要があります。
なぜこれがより良いかより正確ですか?既成の方法はありますか?
Stéphane Chazelasがコメントと2002年の同じスレッドで述べたように、これは無効な文字をブロックしないシェルで実行されるglob拡張と一致しません。おそらくもっと混乱しているのは、リバーステストが名前が破損したファイルだけを一致させることです(bashでcreate fileを使用touch $'D\351marrer' $'Touch\303\251' $'\346\227\245\346\234\254\350\252\236'
)。
$ find -name '*'
.
./Touché
./日本語
$ find -not -name '*'
./D?marrer
したがって、あなたの質問に答えるには、この場合の動作を理解し、関数のfnmatch
戻り値をどのように処理するかを知ることで、find
これを予測できます。おそらく文書を読むだけでは答えが見つかりません。
答え2
探す -name
シェルを使用するオプションパターン一致記号一致するファイル名を実行します。*
パターンです複数文字の一致、ゼロ文字以上の文字列と一致する必要があります。
find
使用マッチパターンマッチングを確認して使用できます。道検査結果:
$ touch $'\U1212'aa
$ touch D$'\351'sinstaller
$ LC_ALL=en_US.utf8 ltrace -e fnmatch find -name '*'
find->fnmatch("foo", "foo", 0) = 0
find->fnmatch("Foo", "foo", 0) = 1
find->fnmatch("Foo", "foo", 16) = 0
find->fnmatch("*", ".", 0) = 0
.
find->fnmatch("*", "D\351sinstaller", 0) = -1
find->fnmatch("*", "\341\210\222aa", 0) = 0
./ሒaa
+++ exited (status 0) +++
一致の失敗を示すにはD\351sinstaller
、fnmatch
returnを使用してください。このような有効な文字と一致します。-1
ሒaa
あなたの場合、UTF-8
ロケールに\351
無効な文字があり、パターンの一致が失敗します。