「echo $(cat /path/to/fileName)」でファイルと方向がリストされるのはなぜですか?

「echo $(cat /path/to/fileName)」でファイルと方向がリストされるのはなぜですか?

でファイルの内容を印刷するとecho $(cat /path/to/filename)、ファイルと指示もリストされます。 しかし、 で実行するとprintf "$(cat /path/to/filename)\n"正常に動作します。

また、それを変数に保存しcontent='cat /path/to/filename'( もcontent=$(cat /path/to/filename)、 で印刷してみましたecho $contentが、同じ結果になりました (ファイルと方向の一覧が表示されます)。

ファイルの内容を変数に保存し、その変数を次のコマンドの入力としてスクリプトに渡したいと思います。

ファイルの内容には特殊文字が*含まれていることに注意してください。

答え1

コマンド置換を実行した後、引用符で囲まない場合は、シェルは結果に対して単語分割 (またはフィールド分割) を実行するためです。

POSIXの定義単語の拡張として:

単語の拡張順序は次のようになります。

  1. チルダ展開 (チルダ展開を参照)、パラメータ展開 (パラメータ展開を参照)、コマンド置換 (コマンド置換を参照)、および算術展開 (算術展開を参照) が最初から最後まで実行されます。トークン認識の項目 5 を参照してください。

  2. フィールド分割(フィールド分割を参照)は、IFSがnullでない限り、ステップ1で生成されたフィールドの部分に対して実行される。

  3. set -f が有効でない限り、パス名拡張 (パス名拡張を参照) が実行されます。

  4. 引用符の削除 (引用符の削除を参照) は常に最後に実行する必要があります。

あなたの場合、*現在の作業ディレクトリ内のすべてのものが一致しました。期待される出力を得るには、結果を引用符で囲む必要があります。

echo "$(cat /path/to/fileName)"

答え2

引用:

$ echo "*" >> test
$ echo $(cat test)
bash43-001 bash43-002 bash43-003 bash43-004 bash43-005 test
$ echo "$(cat test)"
*

最初のルールとして、コマンド置換は常に引用符で囲みます。

グロブをオフにするか (または)、引用符/エスケープしない限り、裸の部分*は で展開されます: 。コマンド出力では、常に引用符を使用するのが最適です。bashset -fsetopt noglob"*" \*

関連情報