最近気づきました。POSIX仕様find
-maxdepth
ジュニアレベルは除外されます。
慣れていない人のために説明すると、主な目的は -maxdepth
下降の深さを制限することです。明らかにするfind
-maxdepth 0
ただ処理中のコマンドライン引数、-maxdepth 1
結果はコマンドライン引数などでのみ直接処理されます。
-maxdepth
POSIX指定オプションとツールのみを使用してPOSIX以外のマスターデータベースと同じ動作を得るにはどうすればよいですか?
-maxdepth 0
(注:もちろん、最初のオペランドとして使用して同じ結果を得ることはできますが、-prune
他の深さには拡張されません。)
答え1
@meuhの-maxdepth 1
アプローチは、まだfind
レベル1ディレクトリの内容を読んでから無視できるため、非効率的です。また、一部のディレクトリ名に、ユーザーロケールで有効な文字を形成しないバイトシーケンスが含まれている場合(たとえば、他の文字エンコーディングのファイル名など)、find
一部の実装(GNUを含む)では正しく機能しません。find
find . \( -name . -o -prune \) -extra-conditions-and-actions
これはGNUを実装するより標準化された方法です-maxdepth 1
。
-mindepth 1 -maxdepth 1
一般的に言えば、(深さ0)について考えたくないので、望む深さは1()です。.
これははるかに簡単です。
find . ! -name . -prune -extra-conditions-and-actions
の場合は-maxdepth 2
次のようになります。
find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
ここで無効な文字の問題が発生します。
たとえば、ディレクトリがありますが、iso8859-1(latin1とも呼ばれる)文字セット(0xe9バイト)でエンコードされている場合Stéphane
(é
2000年代半ばまで西ヨーロッパと米国で最も一般的です)、0xe9バイトUTF-8では有効な文字ではありません。したがって、UTF-8ロケールでは、*
ワイルドカード(一部の実装の場合)が0以上なので一致find
しません。Stéphane
*
数値0xe9は文字ではありません。
$ locale charmap
UTF-8
$ find . -maxdepth 2
.
./St?phane
./St?phane/Chazelas
./Stéphane
./Stéphane/Chazelas
./John
./John/Smith
$ find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St?phane/Chazelas/age
./St?phane/Chazelas/gender
./St?phane/Chazelas/address
./Stéphane
./Stéphane/Chazelas
./John
./John/Smith
鉱山は、find
上記のように、出力が端末に到達すると誤った0xe9バイトを表示します?
。 dでSt<0xe9>phane/Chazelas
はないことがわかりますprune
。
次の手順でこの問題を解決できます。
LC_ALL=C find . \( ! -path './*/*' -o -prune \) -extra-conditions-and-actions
ただし、これはすべてのロケールとfind
実行中のすべてのアプリケーション(-exec
述語など)に影響します。
$ LC_ALL=C find . \( ! -path './*/*' -o -prune \)
.
./St?phane
./St?phane/Chazelas
./St??phane
./St??phane/Chazelas
./John
./John/Smith
これで本当にわかりますが、-maxdepth 2
2番目のStéphaneのéはUTF-8で正しくエンコードされ、éに対して??
UTF-8でエンコードされた0xc3 0xa9バイトとして表示されます(Cロケール単一の未定義文字では2として扱われます)。 ): C ロケールで印刷できない文字です。
を追加すると、-name '????????'
無効なStéphane(iso8859-1でエンコードされたもの)が表示されます。
代わりに任意のパスに適用するには、.
次のようにします。
find some/dir/. ! -name . -prune ...
または-mindepth 1 -maxdepth 1
:
find some/dir/. \( ! -path '*/./*/*' -o -prune \) ...
のための-maxdepth 2
。
私はまだ一つを作ります:
(cd -P -- "$dir" && find . ...)
第1に、これは経路が短くなり、遭遇する可能性が減少するからである。パスが長すぎますまたは引数のリストが長すぎます。これは問題であるだけでなく、find
任意のパスパラメータをサポートできないという事実(-f
FreeBSDを除く)を処理するためです。なぜなら、任意のパスパラメータはまたは...などのfind
値のために窒息する可能性があるからです。$dir
!
-print
否定との組み合わせは、/ inの-o
2つの別々のセットを実行する一般的なトリックです。-condition
-action
find
ファイル会議で独立して-action1
実行する場合は、次のことはできません。-condition1
-action2
-condition2
find . -condition1 -action1 -condition2 -action2
-action2
次の条件を満たすファイルでのみ実行されるため両方状況。
いいえ:
find . -contition1 -action1 -o -condition2 -action2
-action2
以下の条件を満たすファイルに対しては実行されないため両方状況。
find . \( ! -condition1 -o -action1 \) -condition2 -action2
仕事が\( ! -condition1 -o -action1 \)
決める本物各ファイルに。常に返す操作であるとします-action1
(例:-prune
、)。-exec ... {} +
本物。同様の操作の場合は-exec ... \;
返されることがあります。間違った、無害ですが返される別の-o -something
場所を追加できます。-something
本物-true
GNUのfind
or-links +0
または! -name ''
orと同じです-name '*'
(無効な文字については上記を参照してください)。
答え2
これを使用して、-path
与えられた深さを一致させ、そこからトリミングすることができます。例えば
find . -path '*/*/*' -prune -o -type d -print
*
match .
、*/*
match ./dir1
、matchが切り捨てられるため、最大深さは1です*/*/*
。./dir1/dir2
絶対起動ディレクトリを使用している場合は/
前に-path
。
答え3
.
複数のパスを検索するとき(ただではなく)深さを制限する方法が必要な問題に遭遇しました。
たとえば、
$ find dir1 dir2 -name myfile -maxdepth 1
これにより、-regexを使用する代替手段が生じました。主な点は次のとおりです。
-regex '(<list of paths | delimited>)/<filename>'
したがって、上記は次のようになります。
$ find dir1 dir2 -name myfile -regextype awk -regex '(dir1|dir2)/myfile' # GNU
$ find -E dir1 dir2 -name myfile -regex '(dir1|dir2)/myfile' # MacOS BSD
ファイル名なし:
$ find dir1 dir2 -name myfile -maxdepth 1 # GNU
-regex '(<list of paths | delimited>)/<anything that's not a slash>$'
$ find dir1 dir2 -name myfile -regextype awk -regex '(dir1|dir2)/[^/]*$' # GNU
$ find -E dir1 dir2 -name myfile -regex '(dir1|dir2)/[^/]*$' # MacOS BSD
最後に、-maxdepth 2
正規表現を次のように変更します。'(dir1|dir2)/([^/]*/){0,1}[^/]*$'