次のような特定の文字で始まるすべてのファイルを見つけたいです。
find . -maxdepth 1 \( -name "^m*" -a ! -name "g$" \) -print
しかし、誰かが名前に特殊文字を含むファイルを作成した場合はどうなりますか?例えば
touch "
marst"
基準を満たしても検出されません。スペースで始まるファイルを見つけるには、コードをどのように変更する必要がありますか?
また、\( -name "^m*" -a ! -name "g$" \)
findのファイルが「marr」ではなく「./marr」なので、機能しません。これは何も見つからないことを意味します。単語の先頭に一致するようにコードをどのように変更できますか?
答え1
-name
常に名前だけが一致します。つまり、パスと一致しません。みんな名前。その値は正規表現ではなくパターンなので、次のようにしてm
開始するファイル名を見つけることができます。
-name 'm*'
g
そして次に終わる名前
-name '*g'
正規表現を使用するには、-regex
オプションを参照してください。
答え2
改行文字で始まるファイルまたは次のファイル名を一致させるには、次のようにしますm
。
NL='
'
find . \( -name 'm*' -o -name "*${NL}m*" \) -print
少なくとも GNU の場合、find
有効な*
文字シーケンスを形成しないバイトシーケンスは一致しません。これが潜在的な問題であれば、Cロケールを使用する方が良いでしょう。
LC_ALL=C find . \( -name 'm*' -o -name "*${NL}m*" \) -print
例:
$ touch mom $'two\nminutes' $'mad\x80'
$ find . -name 'm*'
./mom
$ find . \( -name 'm*' -o -name "*${NL}m*" \) -print
./two?minutes
./mom
$ LC_ALL=C find . \( -name 'm*' -o -name "*${NL}m*" \) -print
./mad?
./two?minutes
./mom
次から始まるm
が終わらない行を含むファイル名の場合g
:
LC_ALL=C find . \( -name 'm*' -o -name "*${NL}m*" \) ! \(
-name '*g' -o -name "*g${NL}*" \) -print
一部のfind
実装では、ファイルマッチングのための非標準オプションがあります。道(通常はそうではありません。名前)正規表現を使用しますが、実装によって動作が異なるため、ここでは必要ありません。
m
たとえば、正規表現が必要な場所は、名前が終わる行で始まらないファイルを見つけることですg
(例:nor$'cat\nman\ndog'
ではない)。$'plate\nmug\ncup'
$'cat\nman\nmug'
GNUの使用find
:
LC_ALL=C find . -regextype posix-extended -regex \
".*/(([^m$NL/][^/$NL]*|m[^/$NL]*[^$NL/g]|m|)($NL|\$))*"
m
または、名前が次のように始まり、終わらない行が1つ以上あるファイルg
(に似てい$'mad\nmug'
ませんが$'ming\nmong'
):
LC_ALL=C find . -regextype posix-extended -regex \
".*/([^/]*$NL)?m([^$NL/]*[^g$NL/])?(\$|${NL}[^/]*)"
答え3
この-regex
フラグを使用して、globが提供するより複雑な一致が必要かどうかを確認できます。フルパスと一致するため、ファイル名部分のみを一致させるには、次のようにします。
find . -maxdepth 1 -regex '/[
]?m[^/]*[^g]$' -print
参考にしてくださいこの回答改行文字を一致させるために使用できないため、要求したため、文字クラス\n
にスペースを含む改行文字を入れます。
答え4
^
findでは、theまたはtheを$
単純な名前として使用する必要はありません。
用途を探すモデル名前のため。パターンは次のとおりです。
- フルネームと一致します。最初から最後まで。いつも。
- findは、このパターンを使用する前に見つかったすべてのファイルのパスを削除します。
- 唯一の特殊文字は
*
?
and[ ]
(^または$ではありません)です。
m
したがって、で始まるファイルを一致させるにはいいえ次に終わりますg
:
find . -maxdepth 1 -name 'm*[!g]' -o -name 'm'
'm'
ファイルに文字が1つしかない場合を扱います。
ただし、作成したファイルtouch $'\nmarst'
(たとえば、bashのように改行を作成できます)は、new-lineで始まるのではなく、m
new-lineで始まります$'\n'
。単純モードでは置き換える方法はありませんが、-o
findのOR()オプションを使用できます。
find . -maxdepth 1 \( -name 'm*' -o -name $'\n'"m*" \) -a ! -name '*g'
要件が長くなるとこれは難しくなります。
非常に複雑な文字列の場合は、-regex
findオプションを使用できます。