「ls」と「echo $(ls)」の違い


27

2つのシェルサンプルを検討します。

$ ls
myDoc.html
SomeDirectory
someDoc.txt

そして

$ echo $(ls)
myDoc.html SomeDirectory someDoc.txt

ls私が理解しているように、現在の作業ディレクトリの内容をstdoutファイルに追加する最初の実行(ターミナルが表示するものです)。これは正しいです?

2番目は、lsコマンドの値(つまり、現在の作業ディレクトリの内容)を取得し、stdoutファイルに出力します。これは正しいです?

2つのコマンドが異なる出力を与えるのはなぜですか?


1
エコーをしているからです。echoコマンドへの入力としてのlsの出力。
あきだえもん

これは「予想される」動作であり、誰かがすぐに説明します。しかし、lsそれ自体では行ごとに複数のアイテムを提供しないと確信していますか?
ロアイマ

@roaima columnized lsはbsdの「機能」の名残です。UNIXバージョンは1行に1つのエントリを印刷します
スティーブコックス

@SteveCox SVR4の初期から適切なUNIXを使用していなかったため、記憶が少しぼんやりしています。お知らせいただきありがとうございます。
ロアイマ

どうしてecho *
jdh8

回答:


70

このコマンドを実行すると:

ls

端末はの出力を表示しますls

このコマンドを実行すると:

echo $(ls)

シェルはの出力をキャプチャし、その上で単語分割$(ls)を実行します。デフォルトでは、これは、改行文字を含むすべての空白スペースのシーケンスが単一の空白に置き換えられることを意味します。そのため、の出力が1行に表示されます。IFSecho $(ls)

単語分割の高度な説明については、GregのFAQを参照してください

単語分割の抑制

シェルは、引用符で囲まれた文字列に対して単語分割を実行しません。したがって、次の方法で単語の分割を抑制し、複数行の出力を保持できます。

echo "$(ls)"

ls および複数行出力

場合によっては、ls1行に複数のファイルが印刷されることがあります。

$ ls
file1  file2  file3  file4  file5  file6

これは、の出力がls端末に送られるときのデフォルトです。出力が直接端末に送信されない場合、lsデフォルトを1行に1ファイルに変更します。

$ echo "$(ls)"
file1
file2
file3
file4
file5
file6

この動作はに文書化されていman lsます。

別の微妙な点:コマンドの置換と末尾の改行

$(...)あるコマンド置換との出力から改行文字を末尾シェル削除し、コマンド置換が。デフォルトでechoは、出力の最後に1つの改行が追加されるため、これは通常目立ちません。したがって、の終わりから1つの改行を失い、から1つの改行$(...)を獲得してもecho、変更はありません。ただし、コマンドの出力が2つ以上の改行文字で終了しecho、1つだけ追加された場合、1つ以上の改行が出力されなくなります。例として、printf末尾の改行文字を生成するために使用できます。次のコマンドは両方とも、改行の数が異なっていても、1つの空白行の同じ出力を生成することに注意してください。

$ echo "$(printf "\n")"

$ echo "$(printf "\n\n\n\n\n")"

$ 

この動作はに文書化されていman bashます。

もう1つの驚き:パス名の展開、2回

3つのファイルを作成しましょう。

$ touch 'file?' file1 file2

違いを観察ls file?してecho $(ls file?)

$ ls file?
file?  file1  file2
$ echo $(ls file?)
file? file1 file2 file1 file2

の場合echo $(ls file?)、ファイルglob file?2回展開され、ファイル名file1file2出力に2回表示されます。これは、Jeffiekinsが指摘しているように、パス名の展開は最初にls実行される前にシェルによって実行され、次に実行される前に再度echo実行されるためです。

二重引用符を使用した場合、2番目のパス名展開は抑制できます。

$ echo "$(ls file?)"
file?
file1
file2

4
さらに、isattystdoutがttyであるかどうかを使用して確認できます。lsはこれを使用して、色を使用するかどうかを決定します。
ヤヌストロエルセン

1
最後のコードスニペットで引用符が一致していませんか?または$( )、補間する必要がないように、実際に構文バリアを提供しますか?

6
@cat $()は構文障壁を提供します。
Random832

2
もう1つの重要な違い:ファイル名にワイルドカード文字が含まれている場合、echoコマンドはワイルドカード展開します。たとえば、ファイルをls返す場合は?file1 file2、それecho $(ls)からfileを返しますか?file1 file2 file1 file2
ジェフィーキンズ

1
@Jeffiekins echoはワイルドカードを展開しません。シェルは、結果の展開をに引数として渡す前に行いechoます。
-chepner

0

ls 出力を端末に送信しているかどうかを認識しています。

lsコマンドプロンプトで実行すると、擬似ttyに書き込みます。の出力をリダイレクトするlsことは、通常、疑似ttyに送られls、出力を異なる形式にします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.