find
次のようなカレントディレクトリの一部のファイルを収集するために使用するスクリプトから
$ find . -name "*.h"
./foo.h
さて、プレフィックスfoo.h
なしで出力するだけです。空の./
文字列は、""
シェルコマンドの現在のディレクトリを表すようです。しかし、これは以下を提供します:
$ find "" -name "*.h"
find: ftsopen: No such file or directory
だから私は間違っていた。今私の質問は、いつ/どのように/どこ/.. "空の文字列(?)"は、ファイル名またはパス名を必要とするコマンドの現在のディレクトリを意味しますか?簡潔で啓発的な説明はありますか?
追加の質問は、上記の検索項目を文字列操作la${parameter#word}
またはcut
またはsed
?なしで簡単に解決できるかどうかです。
答え1
答え2
あなたはそれを使用することができます:
find * -name "*.h"
.で始まる名前を持つ現在のディレクトリのファイルは.
無視され、.で始まる名前を持つファイルは-
オプションとして解釈され、混乱を招くため、find
これはfind . …
.
/
ファイル名に""で終わる文字列はありません。ヒント現在のディレクトリですが、これは現在のディレクトリが次のようになるわけではありません。表現する空ストリング
答え3
通常、空の文字列は、シェルコマンドやシステムコールの場合、現在のディレクトリを表しません。一部の古いシステムでは機能しますが、POSIX互換システムでは機能しません。。
場合によっては、空の文字列を渡し、プログラムにディレクトリ名が必要な場合は、プログラムが現在のディレクトリを使用していることがわかります。これは意図的な場合もあり、与えられた文字列がスラッシュで始まらないときに現在のディレクトリへの絶対パスを前に追加する副作用によるものもあります。
あなたにとって最高のものは残すことです./
。害はありません。
ファイルリストが次の場合
find . … | sed 's!^\./!!'
これにより、改行文字を含む一部のファイル名が破損する可能性があります。これは一般的に人間が消費することには問題にはならず、 の出力はfind
指定されないのでプログラム消費には適していません。プログラムの使用に適したものを使用している場合は、-print0
おそらくプレフィックスを気にしません./
。
find * …
代わりに使用できますが、欠点があり、一般的に次のような場合には適していませんfind . …
。find *
.
省略しています。- すべてのドットファイル(名前または..`で始まるファイル
.
)は省略されます。 - 現在のディレクトリに(または...という名前のファイル)で始まるファイル名がある場合、オプションまたは
-
述語として解釈されます。!
(
find
フィルタが現在のディレクトリを除外する場合、最初のものは重要ではありません。 2番目の点では、パターンを使用して..?* .[!.]* *
現在のディレクトリ内のすべてのファイルと一致させることができますが、各パターンが1つ以上のファイルと一致することを確認し、一致しない場合は無視する必要があります。可能ですが、非常に面倒です。最後のビットはストッパーです。したがって、find *
高速コマンドラインの使用には適していますが、スクリプトでは使用しないでください。
別のアプローチは、シェルの再帰的グロービング機能を使用することである。
printf '%s\n' **/*.h
shopt -s globstar
これにはbashとksh93を介したアクティベーションが必要であり、デフォルトのset -o globstar
POSIXシェル(たとえばdash)には存在しません。ドットファイルはデフォルトでは移動されません。これを含めるには、まずshopt -s dotglob
bashまたはksh93FIGNORE='@(.|..)'
でドットファイルを無視しないようにglobbingを有効にします。また、このコマンドは一致するものがない場合にパターンを印刷します。 bashで実行するとshopt -s nullglob
空白行が印刷され、~(N)**/*.h
kshでパターンが使用されます。
zshでは、デフォルトでは再帰ワイルドカードが有効になっています。 glob修飾子を使用D
してドットファイルを含め、N
一致するものがない場合は空白行を印刷します(デフォルトでは、パターンがファイルと一致しない場合はzshはエラーを発生させます)。printf
上記のように使用する
print -rl -- **/*.h(DN)
答え4
いくつかのトリックを使用して、先行することなくfind出力を取得できます./
。
findの
-printf
オプションを使用して印刷するように指示します%f
。バラよりman find
:%fはすべての先行ディレクトリファイル名を削除します(最後の要素のみ)。
たとえば、
find . -name "*.h" -printf "%f\n"
解析出力:
find . -name "*.h" | sed 's#^./##'
-
find * -name "*.h"
他の質問では、空の文字列は現在のディレクトリを表していません。さまざまなプログラムが現在のディレクトリをデフォルトのディレクトリとして持っているので、引数なしで実行すると、現在のディレクトリで実行されるだけです。