web-dev-qa-db-ja.com

`* /`がBashまたはZshで何を意味するかについての明確な答えはどこにありますか?

_*/_の意味について、UnixおよびBashに関するO'Reillyからの参照を調べようとしましたが、見つかりませんでした。 _echo */_を実行して、すべてのディレクトリを確認できます。

_*_が「すべてのファイルとディレクトリ」を意味するのに対し、それはすべての「ディレクトリ」のみを意味するように見えますが、何らかの理由で、多くのユーザーはそれを知らないようで、本でも言及されていません。

_*/_の意味とそのバリエーションについて説明している決定的なソースはありますか?

9
nonopolarity

POSIX仕様 は、unixツールがどのように動作するかについての最も確実なリファレンスです。 パス名解決に関するセクション は、ファイル名の末尾のスラッシュの意味を説明しています。

少なくとも1つの非<slash>文字を含み、1つ以上の末尾の<slash>文字で終わるパス名は、末尾の<slash>文字の前の最後のパス名コンポーネントが既存のディレクトリまたはディレクトリエントリを指定しない限り、正常に解決されません。これは、パス名が解決された直後にディレクトリ用に作成されます。

つまり、_foo/_は、fooが既存のディレクトリ、またはプログラムが作成するディレクトリである必要があります(したがって、_mkdir foo/_が許可されます)。 fooが他のタイプのファイル(通常のファイル、名前のパイプなど)である場合、_foo/_としてアクセスすることはできません。

上記の文は不完全です:_foo/_は実際にはディレクトリへのシンボリックリンクを参照する有効な方法です。これは以下で指定されます:

パス名の解決中にシンボリックリンクが検出された場合の動作は、パス名コンポーネントがパス名の末尾にあるかどうか、および実行される機能によって異なります。次のすべてに該当する場合、パス名の解決は完了しています。

1.これは、パス名の最後のパス名コンポーネントです。 2.パス名に末尾がありません。 3.関数はシンボリックリンク自体に作用する必要があります。または、特定の引数は、関数がシンボリックリンク自体に作用するように指示します。

他のすべての場合、システムは残りのパス名があれば、その前にシンボリックリンクの内容(…)を付けます。

つまり、fooがシンボリックリンクであり、プログラムがシンボリックリンクをたどると想定されている場合、_foo/_はリンクのターゲット(ディレクトリである可能性があります)と同等です。したがって、fooがディレクトリへのシンボリックリンクである場合、_foo/_はこのディレクトリを参照する有効な方法です。ただし、fooが通常のファイルまたは他の非ディレクトリのシンボルである場合、_foo/_はそのファイルを参照する有効な方法ではありません。

open などの関数は、既存の非ディレクトリである末尾にスラッシュを含むパス名を指定すると、エラーENOTDIRを返します。

[ENOTDIR]
(…)_O_CREAT_と_O_EXCL_は指定されていません。パス引数には、少なくとも1つの非<slash>文字が含まれ、1つ以上の末尾の<slash>文字で終わり、最後のパス名コンポーネントは、ディレクトリでもディレクトリへのシンボリックリンクでもない既存のファイルを指定します(…)

_*/_のスラッシュの影響については、暗黙的に sh のパターンマッチングに関するセクションを参照してください。パターン内の_/_には特別な規則はありません(ブラケット式に表示できないという規則はここでは関係ありません)。したがって、パターン内の_/_は、パス名内の_/_と一致する必要があります。たとえば、パターン_*/_は_foo/_に一致しますが、fooには一致しません。したがって、_*/_は、ディレクトリおよびディレクトリへのシンボリックリンクに一致しますが、通常のファイル、通常のファイルへのシンボリックリンク、壊れたシンボリックリンク、名前付きパイプなどには一致しません。

*/がディレクトリのみと一致する必要があるいくつかのヒントはbashマニュアルです(強調は私のものです):

  1. *
    null文字列を含むすべての文字列に一致します。 globstar Shellオプションが有効で、パス名展開コンテキストで*が使用されている場合、単一のパターンとして使用される2つの隣接する*は、すべてのファイルと0個以上のディレクトリおよびサブディレクトリに一致します。 /が続く場合隣接する2つの* s ディレクトリとサブディレクトリのみに一致します

    **/はディレクトリとサブディレクトリのみに一致するという点で明示的です。これは、*/も一致する必要があることを意味しているように見える場合があります。

  2. グロブスター
    設定されている場合、パス名展開コンテキストで使用されるパターン**は、すべてのファイルと0個以上のディレクトリおよびサブディレクトリに一致します。 パターンの後に/が続く場合、ディレクトリとサブディレクトリのみが一致します

    上記のヒントの繰り返し。

そしてzshマニュアルでは:

  1. -gグロブストリング
    グロブストリングは、ファイル名グロビングを使用して展開されます。即時の拡張から保護するために引用する必要があります。結果のファイル名は、可能な補完として扱われます。 Use`*(/)'ディレクトリの場合は`*/'の代わりに

    これは、*/がディレクトリを意味することを明示的に示しています他の場所で

しかし、唯一の実際の確認は、kshマニュアルからのものです。

*
null文字列を含むすべての文字列に一致します。ファイル名の展開に使用する場合、globstarオプションがオンの場合、2つの隣接する*自体がすべてのファイルと0個以上のディレクトリおよびサブディレクトリと一致します。 /が後に続く場合、ディレクトリとサブディレクトリのみが一致します

これは、単一の*が何をすべきかについて明確に明確です。

POSIXは主にkshの動作方法に基づいていて、bashとzshがkshの動作方法をエミュレートしようとしていることを考えると、この同じ機能が3つのマニュアルすべてで繰り返されることを期待するのは妥当です。

2
Isaac

bashマニュアルのパターンマッチング に説明があります。

3.5.8.1パターンマッチング

下記の特殊パターン文字以外のパターンに現れる文字は、それ自体と一致します。 NUL文字はパターンでは使用できません。バックスラッシュは次の文字をエスケープします。エスケープするバックスラッシュは照合時に破棄されます。特殊パターン文字は、文字どおりに一致させる場合は引用符で囲む必要があります。

特殊パターン文字には次の意味があります。

*

Null文字列を含む任意の文字列に一致します。 globstar Shellオプションが有効で、(* =)がファイル名展開コンテキストで使用されている場合、2つの隣接する '*'が単一のパターンとして使用されますすべてのファイルと0個以上のディレクトリおよびサブディレクトリに一致します。 「/」が後に続く場合、2つの隣接する「*」はディレクトリとサブディレクトリのみに一致します。

そして The Linux documentation projectecho*

Bashは、引用符で囲まれていないコマンドライン引数に対してファイル名の展開を実行します。 echoコマンドはこれを示しています。

bash$ echo * a.1 b.1 c.1 t2.sh test1.txt`

bash$ echo t* t2.sh test1.txt

bash$ echo t?.sh t2.sh```

*/の展開は、シェルにとって特別な意味はありません。これは、*.txtを展開すると、.txtで終わるすべての既存のパス名がリストされます。

anyシェルの場合、*/は、/で終わるすべてのアクセス可能なパス名に展開されます。

その場合の唯一の問題は、pathname/で終わる可能性があることを理解することです。

これは、最後のファイル名が存在し、ディレクトリである場合にのみ可能です。

明示的な確認(man kshから):

*
... /が続く場合は、ディレクトリとサブディレクトリのみが一致します。

0
Isaac