ls -dもファイルをリストするのはなぜですか?


48
  • 指定するときは、次でls --directory a*始まるディレクトリのみをリストする必要がありますa*
  • ただし、次で始まるファイルとディレクトリをリストします a

質問

  • どこ私は以外に、この上でいくつかのドキュメントを見つけるかもしれないmanし、info私が思うところ、私は徹底的に見えましたか?
  • これはBASHでのみ動作しますか?


5
echo a*a(もしあれば)で始まるファイルもリストします。これを行うのlsはbashではなく、より明確にするためです。
ash108

回答:


89

a*そして*a*構文はしないことによって、シェルによって実装されるlsコマンド。

入力するとき

ls a*

シェルプロンプトで、シェルはa*、名前がで始まる現在のディレクトリ内の既存のすべてのファイルのリストに展開されますa。たとえばa*、シーケンスa1 a2 a3に展開し、それらを引数として渡すことができますlslsコマンド自体は見たことがない*文字を、それだけで3つの引数を見てa1a2a3

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

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

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

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

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

mv *.log *.log.bak

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

find . -name '*.txt' -print

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

mv *.log ..

あなたが忘れた場合..

mv *.log

.log現在のディレクトリに2つのファイルが存在する場合、次のように展開されます。

mv one.log two.log

これは名前を変更one.logして上書きしtwo.logます。

編集:そして、52のアップ投票、承認、および達人バッジの後、タイトルの質問に実際に回答する必要があります。

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

ls -l a*

lsは、名前がで始まる各ファイルと、名前がで始まる各ディレクトリa内容の長いリストを提供しますa。ファイルとディレクトリのリストが必要な場合は、それぞれ1行で、次を使用できます。

ls -ld a*

次と同等です:

ls -l -d a*

lsコマンドが*キャラクターを見ることがないことをもう一度思い出してください。

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

そして、もちろん、専門家でさえ時々ドキュメントを参照する必要があります。この古典的なジョークも参照してください。


8
@Thomas:名前がで始まる現在のディレクトリ内a*のすべてのファイルのリストに展開します。a
キーストンプソン

2
@Thomas:または指定したディレクトリ内:ls subdir/a*
キーストンプソン

1
シェルの展開後に実行されたコマンドを実際に見るには、echoそれです。そのため、何が起こっているかを知りたい場合はls a*、最初に実行しますecho ls a*
カルロスキャンデロス

1
または単にecho a*...シェルはとにかくグロブ拡張を行います
役に立たない

2
@sendmoreinfo:それはシェルと設定に依存します。cshおよびtcshでは、失敗したglob展開はエラーです。bashではshopt -s failglob、同じ動作が発生します。設定nullglobではなくfailglob、例えば、原因*nosuchfile*空の文字列に展開します。
キーストンプソン

27

キース・トンプソンの答えをご覧ください。しかし、ls --directory a*ファイルディレクトリが表示される理由を説明するために:この--directoryオプションは、非ディレクトリファイルを抑制しません。代わりに、ディレクトリ自体をリストしますが、そうでなければコンテンツをリストします。例:

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

3
その例は、この-Fオプションにより説得力があります
グレンジャックマン

6

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

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

公平を期すために、「コンテンツではなくエントリ」がおそらくより説明的である可能性があります。

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


-dオプションは(簡潔であれば)マニュアルページで説明されているかもしれませんが、引数の拡張とワイルドカードはシェルによって行われるため、lsのマニュアルページには記載されていません。シェルでファイル名の展開をオフにした場合、「ls a *」は文字通り「a *」という名前のファイルのみを表示します。
ジョニー

シェル展開については、他の回答者から回答がありましたが、つまらないものであり、不十分な説明や誤読の可能性に対処するものはありません。すでによく言われたことを繰り返してください。
msw

4

グロビング

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

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

ディレクトリ

ls -dディレクトリと同様にファイルをリストする理由について...

lsmanページでは、これがなぜ起こるかが、非常に簡潔な説明と、説明しています。そのため、ここでは詳細な説明を試みています。

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

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

要約するとls、デフォルトでは、パス名を指定するとディレクトリの内容が表示されます。-dこの動作を変更し、標準ファイルに対して行われるように、ディレクトリ名のみを表示します。


3

ドキュメンテーションは、ディレクトリ名を受け取るとその内容ではなくディレクトリエントリをリストするのではなく、ディレクトリエントリのみをリストするとは言いません。理解するための最良の方法は例です:ls

> {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 /

2

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

Bourne互換シェル単語展開のシーケンスは次のとおりです。

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

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


1

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


3
「パス名の展開」または「ファイル名の生成」に似ています。「パターンマッチング」に関連していますが、同じではありません。
ステファンシャゼル

@StephaneChazelas確かに、「パターンマッチング」はマニュアルページの「パス名展開」のサブセクションですが、「ファイル名の生成」はまったくありません(情報ドキュメントのみ)。
ハウケレイジング
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.