複数のファイルを複数のディレクトリにコピーする

複数のファイルを複数のディレクトリにコピーする

異なるディレクトリに多数のファイルをコピーする際に問題が発生します。詳しく説明しましょう:

ディレクトリに次のものがあるとします。

$ ls
file1 file2 file3 file4 file5 dir1 dir2 dir3

そして、1 つのコマンドですべての dir* 内のすべてのファイル* をコピーしたいです。私は次のように試しました:

 echo dir{1..3} | xargs cp file{1..5} '{}' \;

私の意図は、xargs に echo からのすべての dir* を処理し、処理された入力内のすべてのファイルをコピーするように指示することでしたが、これと類似の方法は機能しませんでした。約 20 個のディレクトリに対して繰り返す必要があるタスクであり、ファイル名がわずかに異なるため、スクリプトの使用は避けたいと思います。そのため、スクリプトではなくコマンドを変更することを希望します。

答え1

echo dir[1-3] | xargs -r -n1 cp file[1-5]

答え2

xargs の使い方に小さな間違いがあります。-n パラメータがない場合、xargs は入力のすべてのパラメータをコマンドに追加し、echo dir{1..3}各エントリ間に必要なキャリッジ リターンを追加しないため、xargs は結果を 1 つのパラメータと見なします。

xargs にはエントリの数を制限できるオプション -n があり、区切り文字として \n または \0 を使用してディレクトリをリストする必要があります。

find . -mindepth 1 -maxdepth 1 -type d -print0 | xargs -0 -n 1 cp file{1..5}

find コマンドは現在のディレクトリ内のすべてのディレクトリを検索し、\0 を区切り文字として使用します (スペースを含むディレクトリがある場合に有効です)。xargs は \0 を区切り文字として使用し、毎回 1 つのパラメータのみを使用してコマンドを起動します。

答え3

本当にそのような名前を持っている場合は、次のようなものが機能するはずです。

#!/bin/bash
shopt -s nullglob
for dir in dir*/; do
    cp file* "$dir"
done

名前に関係なくすべてのファイルをすべてのディレクトリにコピーする場合:

#!/bin/bash
shopt -s nullglob dotglob
for dir in */; do
    for file in *; do
        [[ -f $file ]] && cp "$file" "$dir"
    done
done

答え4

もうすぐ完了です。 は各ソース ファイルのコピーを 1 つだけ作成するcpため、各宛先ディレクトリごとに個別のコマンドを実行する必要があります。 の主な目的は、複数の引数に対して 1 つのコマンドを実行することですが、 オプションを使用して、一度に 1 つの項目を渡すように指示することもできます。 また、 は の構文です。 では不要です (使用できません) 。cpxargs-n{} ;find … -execxargs

echo dir{1..3} | xargs -n 1 cp file{1..5}

この方法は、ディレクトリ名に空白や文字が含まれていない場合にのみ機能することに注意してください。 は\'"、これらの文字がファイル名の一部であり、入力ファイルを引用符で囲んで区切っていないことを判別できないためですxargs。 このような問題がない別の方法は、シェル ループを使用することです。

for d in dirs{1..3}; do
  cp file{1..5} "$d"
done

これらはすべて、ファイルとディレクトリを名前で簡単に区別できることを前提としています。区別できない場合は、/末尾に を追加することでディレクトリを一致させることができます。たとえば、*/現在のディレクトリ内のすべてのディレクトリに一致し、foo[0-9]*/名前がfooと数字で始まるすべてのディレクトリに一致します。ほとんどのシェルには、ディレクトリ以外のみに一致させる同様の方法はありませんが、cp再帰コピーを作成するように指示するために引数なしでディレクトリを に渡すと、ディレクトリは無視され、エラーメッセージが表示されます。

for d in */; do
  cp * "$d"
done

zshでは、glob 修飾子特定のファイルタイプのみに一致させます。

for d in *(/); do
  cp *(.) $d
done

関連情報