web-dev-qa-db-ja.com

なぜls -dもファイルを一覧表示するのですか?それはどこに文書化されていますか?

  • ls --directory a*を指定する場合、a*で始まるディレクトリのみをリストする必要があります
  • しかし、aで始まるファイルとディレクトリをリストします

質問

  • maninfo以外に、これに関するドキュメントはどこにありますか?
  • これはBASHでのみ機能しますか?
49
erch

a*および*a*構文は、lsコマンドではなく、シェルによって実装されます。

入力すると

ls a*

シェルプロンプトでは、シェルはa*を、現在のディレクトリ内でaで始まる既存のすべてのファイルのリストに展開します。たとえば、a*をシーケンスa1 a2 a3に展開し、それらをlsに引数として渡すことができます。 lsコマンド自体は*文字を認識しません。 3つの引数a1a2、およびa3のみを認識します。

ワイルドカード拡張の目的で、「ファイル」は現在のディレクトリ内のすべてのエンティティを指します。たとえば、a1は通常のファイル、a2はディレクトリ、a3はシンボリックリンクです。それらはすべてディレクトリエントリを持ち、シェルのワイルドカード拡張は、それらのエントリがどの種類のエンティティを参照するかを気にしません。

実際に実行される可能性のあるすべてのシェル(bash、sh、ksh、zsh、csh、tcshなど)は、ワイルドカードを実装しています。詳細は異なる場合がありますが、ゼロ以上の文字に一致する*と単一の文字に一致する?の基本的な構文は、ある程度一貫しています。

特にbashの場合、これはbashマニュアルの「ファイル名の展開」セクションに記載されています。 info bashを実行して「ファイル名の展開」を検索するか、 ここ を参照してください。

これが個々のコマンドではなくシェルによって行われるという事実は、興味深い(そして時には意外な)結果をもたらします。それについての最も良いことは、ワイルドカードの処理が(ほぼ)allコマンドで一貫していることです。シェルがこれを行わなかった場合、必然的にいくつかのコマンドは邪魔にならず、他のものは作者が「より良い」と考えた微妙に異なる方法でそれを行います。 (Windowsのコマンドシェルにはこの問題があると思いますが、さらにコメントするのに十分に慣れていません。)

一方、複数のファイルの名前を変更するコマンドを書くことは困難です。あなたが書く場合:

mv *.log *.log.bak

*.log.bakは、現在のディレクトリに既に存在するファイルに基づいて展開されるため、おそらく失敗します。この種のことを行うコマンドがありますが、独自の構文を使用して、ファイルの名前を変更する方法を指定する必要があります。一部のコマンド(findなど)は、独自のワイルドカード展開を実行できます。シェルの展開を抑制するには、引数を引用する必要があります。

find . -name '*.txt' -print

シェルのワイルドカード展開は、コマンドライン引数の構文と既存のファイルのセットに完全に基づいています。 できないコマンドの意味の影響を受けます。たとえば、すべての.logファイルを親ディレクトリに移動する場合は、次のように入力できます。

mv *.log ..

..を忘れた場合:

mv *.log

たまたま現在のディレクトリにちょうど2つの.logファイルがあると、次のように展開されます。

mv one.log two.log

one.logとclobber two.logの名前を変更します。

[〜#〜] edit [〜#〜]:そして、52件の賛成票、承認、およびグルバッジを取得したら、実際に質問に答える必要がありますタイトルに。

ls-dまたは--directoryオプションは、ディレクトリのみをリストするようには指示しません。内容ではなく、ディレクトリ自体をリストするように指示します。 lsの引数としてディレクトリ名を指定すると、通常はディレクトリのcontentsが一覧表示されます。これは通常、これが目的であるためです。-dオプションは、ディレクトリのみを一覧表示するように指示します。これは、ワイルドカードと組み合わせると特に便利です。入力した場合:

ls -l a*

lsは、名前がaで始まる各fileと、名前が始まる各ディレクトリのcontentsの長いリストを提供しますa。ファイルとディレクトリのリストが必要な場合は、1行ずつ、次のように使用できます。

ls -ld a*

これは次と同等です:

ls -l -d a*

lsコマンドが*文字を認識することはありません。

これが文書化されている場所に関しては、man lsは、ほぼすべてのUnixライクなシステムでのlsコマンドの文書を表示します。ほとんどのLinuxベースのシステムでは、lsコマンドはGNU coreutilsパッケージの一部です。infoコマンドがある場合は、info lsまたはinfo coreutils lsは、より明確で包括的なドキュメントを提供するはずです。MacOSなどの他のシステムでは、lsコマンドの異なるバージョンを使用していて、infoコマンドがない場合があります。これらのシステムではman lsを使用します。_ls --help比較的短い使用法のメッセージ(私のシステムでは117行)ifを使用しますGNU coreutils実装。

そして、はい、専門家でさえ時々ドキュメントを参照する必要があります。 this classic joke も参照してください。

91
Keith Thompson

キース・トンプソンの答えを見てください。しかし、なぜls --directory a*はファイルを表示しますandディレクトリ:--directoryオプションは、ディレクトリ以外のファイルを抑制しません。代わりに、それ自体がディレクトリをリストしますが、それ以外の場合はコンテンツをリストします。例:

$ mkdir foo
$ touch foo/bar
$ ls foo
bar
$ ls --directory foo
foo
27
chirlu

非常に明確にするために、それは ls(1)マニュアルページ に文書化されています:

-d、--directory内容の代わりにディレクトリエントリをリストし、シンボリックリンクを逆参照しません

公平に言うと、「内容ではなくエントリ」のほうが説明的である可能性があります。

FILEがディレクトリの場合、そのディレクトリの内容をリストするのではなく、ディレクトリエントリ自体を表示します。 FILEがシンボリックリンクの場合、リンクが指すファイルではなく、リンクエントリ自体を表示します。

6
msw

グロビング

説明したように、*の拡張(および同様の拡張)はUnixの専門用語ではglobbingと呼ばれ、通常はコマンドプロセッサの機能です(Unixの用語では「シェル」と呼ばれます)。したがって、グロビングは他の多くの場所でも使用できます。 globbingの詳細については、クラシックLinuxディストリビューションのシェルでman 7 globと入力してください(または this を参照)。

初期のUnixでは、globは実際には 別のプログラム と呼ばれ、/etc/globと呼ばれていました(そのドキュメントについては、 この古いUNIXマニュアル の10ページを参照してください)。現在、これはコードライブラリによって提供されるコードルーチンであり、一般的にシェルで使用されます。 ソースWikipedia

ディレクトリ

ls -dがファイルとディレクトリを一覧表示する理由について...

lsのマニュアルページ は、これが発生する理由を説明していますが、非常に簡潔な説明です。だからここに拡張された説明の試みがあります:

デフォルトでは、lsは、名前が指定されたときにディレクトリのcontentsをリストし、ディレクトリへのsymlinksに対して同じことを行います。 -dオプションは、 「ディレクトリの名前が指定された場合」(globbingにより暗黙的にを指定することもできます、ディレクトリの_name_sのみを表示しますが、その内容はではありません。同様に、directoriesへのシンボリックリンクの(明示的またはimplicitly)名を指定すると、シンボリックリンクのファイル名が表示されます、それが参照するディレクトリの内容ではありません。

-dオプションは、どの項目がリストされているかを知る限り、私が知る限り何もしません。これは、find . -maxdepth 1 -type dのように、findで(ソース: here )実行できます。 GNU lsここ でのみこれを行う良い方法があるかどうかはわかりませんが、findコマンドの使用例です。

つまり、デフォルトでは、lsは、パス名を指定すると、ディレクトリの内容を表示します。 -dは、この動作を変更し、標準ファイルの場合と同様に、ディレクトリ名自体のみを表示します。

4
Abbafei

ドキュメントはそれがリストされているとは述べていませんonlyディレクトリエントリバーではなくlsがディレクトリ名を受け取ったときにdirエントリがリストされますの代わりにそれはコンテンツです。理解する最良の方法は例です:

> {ice} ~ :10:47 % ls -l / 
total 97
drwxr-xr-x   2 root root  4096 May  3 00:27 bin
drwxr-xr-x   4 root root  1024 May  3 14:17 boot
drwxr-xr-x   2 root root  4096 Apr 29 13:44 cdrom
drwxr-xr-x  18 root root  4420 May  9 09:58 dev
...
lrwxrwxrwx   1 root root    33 May  3 14:16 vmlinuz -> boot/vmlinuz-3.9.0-030900-generic
lrwxrwxrwx   1 root root    29 May  3 11:07 vmlinuz.old -> boot/vmlinuz-3.8.0-19-generic
> {ice} ~ :10:47 % ls -ld /
drwxr-xr-x 25 root root 4096 May  3 14:16 /
3
defhlt

ドキュメントはShellの一部です。特に、シェルはコマンドを実行する前に、特定の順序でさまざまな拡張と置換を実行します。

Word展開の互換性のあるBourne Shellの場合 のシーケンスは、

  1. チルダ拡張
  2. パラメータ拡張
  3. コマンド置換
  4. 算術展開
  5. フィールド分割
  6. パス名拡張
  7. 見積もりの​​削除

そのため、lsコマンドは*文字すら見えません。引数は、a*グロブパターンに一致するすべてのファイルですでに展開されています。これは、ファイル名の展開を必要とする各コマンドがこの機能自体を実装する必要があるWindowsとは異なります。

2
Jens

必要なキーワード(man bash)は「パス名拡張」です。

1
Hauke Laging