空の文字列はいつ現在のディレクトリを表しますか?

空の文字列はいつ現在のディレクトリを表しますか?

find次のようなカレントディレクトリの一部のファイルを収集するために使用するスクリプトから

$ find . -name "*.h"
./foo.h

さて、プレフィックスfoo.hなしで出力するだけです。空の./文字列は、""シェルコマンドの現在のディレクトリを表すようです。しかし、これは以下を提供します:

$ find "" -name "*.h"
find: ftsopen: No such file or directory

だから私は間違っていた。今私の質問は、いつ/どのように/どこ/.. "空の文字列(?)"は、ファイル名またはパス名を必要とするコマンドの現在のディレクトリを意味しますか?簡潔で啓発的な説明はありますか?

追加の質問は、上記の検索項目を文字列操作la${parameter#word}またはcutまたはsed?なしで簡単に解決できるかどうかです。

答え1

ずっと前( 7版32V4.2BSD4.3BSD)、システムコールレベルで現在の作業ディレクトリを表す長さゼロのパス名。存在する システム3、長さ0のパス名を使用することは、すべての場合にエラーです。POSIX規格パス名の解決については、次のような言葉があります。

空のパス名は正常に解決されません。

答え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 globstarPOSIXシェル(たとえばdash)には存在しません。ドットファイルはデフォルトでは移動されません。これを含めるには、まずshopt -s dotglobbashまたはksh93FIGNORE='@(.|..)'でドットファイルを無視しないようにglobbingを有効にします。また、このコマンドは一致するものがない場合にパターンを印刷します。 bashで実行するとshopt -s nullglob空白行が印刷され、~(N)**/*.hkshでパターンが使用されます。

zshでは、デフォルトでは再帰ワイルドカードが有効になっています。 glob修飾子を使用Dしてドットファイルを含め、N一致するものがない場合は空白行を印刷します(デフォルトでは、パターンがファイルと一致しない場合はzshはエラーを発生させます)。printf上記のように使用する

print -rl -- **/*.h(DN)

答え4

いくつかのトリックを使用して、先行することなくfind出力を取得できます./

  1. findの-printfオプションを使用して印刷するように指示します%f。バラよりman find

    %fはすべての先行ディレクトリファイル名を削除します(最後の要素のみ)。

    たとえば、

    find . -name "*.h" -printf "%f\n"
    
  2. 解析出力:

    find . -name "*.h" | sed 's#^./##'
    
  3. @Anthonのトリック

    find * -name "*.h"
    

他の質問では、空の文字列は現在のディレクトリを表していません。さまざまなプログラムが現在のディレクトリをデフォルトのディレクトリとして持っているので、引数なしで実行すると、現在のディレクトリで実行されるだけです。

関連情報