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

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

2つのシェルサンプルを考えてみましょう。

$ ls
myDoc.html
SomeDirectory
someDoc.txt

そして

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

私が理解したのは、実行される最初の作業は、ls現在の作業ディレクトリの内容をファイルに追加することですstdout(これが端末に表示されるものです)。そうですか?

2番目はコマンドの値ls(現在の作業ディレクトリの内容を意味します)を取得してファイルに印刷しますstdout。そうですか?

これらの2つのコマンドが異なる出力を提供するのはなぜですか?

ベストアンサー1

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

ls

端末に表示される出力ですls

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

echo $(ls)

シェルは出力をキャプチャし$(ls)て実行します。噴射上。IFSすべての空白シーケンスを意味するデフォルト値を使用し、含む改行は単一のスペースで置き換えられます。これが出力が一行echo $(ls)に表示される理由です。

単語の分割に関する高度な議論については、以下を参照してください。グレッグのよくある質問

噴射を抑える

シェルは、引用符付き文字列に対してトークン化を実行しません。したがって、次のように単語の分離を抑制し、複数行の出力を保存することができます。

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は、出力の末尾に改行文字を追加するので、これは通常目立たない。したがって、の終わりに改行を失い、から$(...)改行を得ると、echo何も変わりません。ただし、コマンド出力が次に終了する場合2つ以上改行echo文字を 1 つだけ再追加しても、出力では 1 つ以上の改行文字が失われます。たとえば、末尾の改行を生成するために使用できますprintf。次のコマンドはすべて改行数が異なりますが、1つの空行に同じ出力を生成します。

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

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

$ 

この動作はで説明されていますman bash

もう一つの驚き:パス名拡張、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?)ファイルグローブがfile?拡張された場合二重、ファイル名がfile1出力file2に2回表示されます。 Jeffkinsが指摘したように、これは次のとおりです。パス名拡張実行する前にまずlsシェルで実行し、実行echoする前に再実行してください。

第二パス名拡張二重引用符を使用すると、これを抑制できます。

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

おすすめ記事