なぜこれはシェルの for ループでは機能するのに、それ自体では機能しないのでしょうか

なぜこれはシェルの for ループでは機能するのに、それ自体では機能しないのでしょうか

なぜこれが機能するのか

for X in A* ; do cp $X/output.txt output/$X.txt ; done

しかし、これは違う

cp A*/output.txt output/A*.txt

A1、A2、A3、A4 などという複数のフォルダーから output.txt ファイルを「output」という結合フォルダーにコピーし、各テキスト ファイルに元のフォルダーの名前を付与します。

答え1

シェルがA*.txt部分を拡張するため複数呼び出されるコマンドに渡される前にパスを指定します (cpこの場合は)。

つまり、最初のケースでは、A1.txt、A2.txt、A3.txt、A4.txtという名前のファイルがあり、それぞれoutput.txtを含むディレクトリA1、A2、A3、A4がある場合、次のように展開されます。何かのようなもの:

for X in A1.txt A2.txt A3.txt A4.txt ; do cp $X/output.txt output/$X.txt ; done

2 番目のケースでは、次のように展開されます。

cp A1/output.txt A2/output.txt A3/output.txt A4/output.txt output/A*.txt

このoutput/A*.txt部分は、ディレクトリ内に glob に一致するものが存在するかどうかによって拡張される場合とされない場合outputがあります。存在する場合は、次のようにさらに悪化します。

cp A1/output.txt A2/output.txt A3/output.txt A4/output.txt output/A8.txt output/A9.txt

cp複数のソースファイルが与えられた場合、宛先ファイルが必要ですディレクトリ結局、これをどう処理したらよいか分からず、単に手を上げて代わりにエラーを返します。

答え2

その理由は、 に2つ以上の引数がある場合cp、最後の引数がしなければならないディレクトリになります。cp マニュアルページ状態:

概要

cp [オプション]... [-T] ソース 宛先

cp [オプション]... ソース... ディレクトリ

cp [オプション]... -t ディレクトリソース...

説明

SOURCE を DEST にコピーするか、複数の SOURCE を DIRECTORY にコピーします。

あなたが書いたコマンドは、

  cp file1 file2 file3 file4

意図されていたのは

 cp file1 file3; cp file2 file4

しかし、上記の理由により、そうはなりません。代わりに、for ループは、まさに上記の 2 つのステートメントを生成します。これが、実際に必要なことです。

関連情報