見つかったコンテンツが現在のディレクトリにある場合、Findは条件付きディープ検索を実行しようとします。ファイルを見つけて、その出力を言語として解釈し、それ以外の場合は通常どおりに出力します。
$ find ~+ -maxdepth 1 \( -type f -printf 'File: %p\n' -o -printf '%p\n' \) -o -mindepth 2 -printf '%p\n'
find: warning: you have specified the -mindepth option after a non-option argument (, but options are not positional (-mindepth affects tests specified before it as well as those specified after it)..
なぜ失敗し、そのような要件を解決するには?
答え1
-maxdepth
/ -mindepth
(非標準のGNU拡張ですが、現在はfind
他の多くの実装でサポートされています)はそうではありません。状況ディレクトリへの降り方に影響を与えるグローバルフラグである述語find
。
-maxdepth
標準効果は次の組み合わせで達成できます。-path
-prune
。
FreeBSDfind
-depth n/-n/+
深さn
/ < />のn
ファイルは一致する必要があるため、n
FreeBSDまたは派生製品(macOS、DragonFly BSD ...)では次のようになります。
find ~+ -depth 1 -type f -exec printf 'File: %s' {} ';' -o -print
ここでは-exec printf
GNU固有の-printf
。
技術的にはprintf
失敗する可能性があるため、オーバーライドを-print
使用するとこの問題を解決できますが、表示順序に影響します。または、次のように変更できます。-exec ... {} +
-exec ... {} ';'
find ~+ -depth 1 -type f '(' -exec printf 'File: %s' {} ';' -o -true ')' -o -print
または:
find ~+ '(' ! -depth 1 -o ! -type f ')' -print -o -exec printf 'File: %s' {} ';'
標準的なケースでは、-path
これを代わりに使用できます(それほど単純ではありませんが)。
LC_ALL=C find ~+/. -path '*/./*/*' -print -o \
-type f -printf 'File: %p\n' -o -print
または、深さを2に制限します(私の以前のバージョンの答えと同じようにあなたがそうであると-mindepth 2
仮定します-maxdepth 2
)。
LC_ALL=C find ~+/. -path '*/./*/*' -prune -print -o \
-type f -printf 'File: %p\n' -o -print
(まだGNUに特化した標準ではありません-printf
。)
sの深さ0点を示すために/.
パスに追加します(そうでなければ$PWD
/に表示されないことを保証します)。~+
find
-path
代わりに使用できません-path "$PWD/*/*"
(例:提案された修正$PWD
)これは、ワイルドカードまたはバックスラッシュを含む値では正しく機能しないためです(引数が-path
ワイルドカードパターンとして扱われるため)。
比較する:
$ mkdir -p '[1]/2/3/4'
$ touch '[1]/2/3/4/file'
$ cd '[1]'
$ LC_ALL=C find ~+ -path "$PWD/*/*" -print -o -type f -printf 'File: %p\n' -o -print
/tmp/[1]
/tmp/[1]/2
/tmp/[1]/2/3
/tmp/[1]/2/3/4
File: /tmp/[1]/2/3/4/file
$ LC_ALL=C find ~+/. -path '*/./*/*' -print -o -type f -printf 'File: %p\n' -o -print
/tmp/[1]/.
/tmp/[1]/./2
/tmp/[1]/./2/3
/tmp/[1]/./2/3/4
/tmp/[1]/./2/3/4/file
代替案は追加することです。ただし、一部の実装では追加の後続ビットが削除される//
ため、移植性が低下します。find
/
パイプを介して出力から該当する項目をsed 's:/\./:/:'
削除できます。/./
LC_ALL=C
GNUはこれを必要とし、有効な文字を形成しないバイトシーケンスを含むパスコンポーネントを一致させるfind
ことはできません。*
GNUにはfind
ファイルの深さを明示的に一致させる述語はありませんが、その述語-printf
は印刷その深さ。したがって、ここではFile:
深さ1の一般ファイルに対応するプレフィックスを追加し、いくつかの後処理を実行できます。
find . -printf '%d%y,%p\0' | # print depth, type and path
sed -z 's/^1f,/&File: /' | # add "File: " prefix for regulars at depth 1
cut -zd, -f2- | # remove the depth and type
tr '\0' '\n' # NL delimited for user consumption