cpのコピー先を一度に複数指定する方法

cpコマンドでデータのコピー先を一度に複数指定する方法

cpコマンドでデータのコピーを行う場合、通常はコピー先は1つになります。

ですが、複数のコピー先を「xargs」コマンドに渡してcpコマンドを使用すると、一度にコピー先を複数指定することができます。

複数のコピー先を「xargs」コマンドに渡す方法として、今回はbashの機能つかった3通りを紹介していきます。

・ブレース展開を使用
echo {コピー先1,コピー先2} | xargs -t cp -p コピー元
・forを使用
for i in コピー先1 コピー先2; do echo $i; done | xargs -t -n 1 cp -p コピー元
・whileを使用(ファイルから読み込み)
while read line; do echo "$line"; done < "ファイル" | xargs -t -n 1 cp -p コピー元

今回紹介する方法でデータのコピーを行う場合は、誤ったコピー先をxargsに渡してしまわないか事前に問題ないデータでコピーのテストを行うことをおすすめします。

xargsのオプション

xargsコマンドで使用しているオプションの説明です。

  • -t 実行するとコマンドと引数を表示
  • -n 1 xargsに渡す引数の最大数を1として指定

-t オプション

「-t」オプションを指定すると「cp -p コピー元 コピー先」といったように、実行した内容が表示されます。

実行した内容を表示させる必要がなければ必要はありません。

-n 1 オプション

「-n 1」でxargsに渡す引数の最大数を1つに指定しないと、「コピー先1 コピー先2」がまとめてxargsに渡されてしまいます。

コピー先として「test_dir1」と「test_dir2」を指定して「-n 1」オプションを使わずコピーを実行してみます。

$ echo {test_dir1,test_dir2} | xargs -t cp -p test.txt
cp -p test.txt test_dir1 test_dir2
cp: -r not specified; omitting directory 'test_dir1'

cp -p test.txt test_dir1 test_dir2と表示されているように、「test_dir1 test_dir2」が一度にxargsに渡されてしまいコピーが失敗しています。

bashのブレース展開を使用

bashのブレース展開使い、複数のコピー先をxargsコマンドに渡す方法です。

echo {コピー先1,コピー先2} | xargs -t cp -p コピー元

コピー先を増やす場合は、「,」で区切って「echo {コピー先1,コピー先2,コピー先3} 」といったようにコピー先を追加します。

実行例

テスト用として、下記のような「test.txt」ファイルと「test_dir1」「test_dir2」というディレクトリを用意しました。

$ ls -lR
.:
total 12
-rw-rw-r-- 1 tamohiko tamohiko    5 Apr  9 11:15 test.txt
drwx------ 2 tamohiko tamohiko 4096 Apr 10 00:18 test_dir1
drwxrwxr-x 2 tamohiko tamohiko 4096 Apr 10 00:18 test_dir2

./test_dir1:
total 0

./test_dir2:
total 0

ブレース展開を使用して「test_dir1」と「test_dir2」を「xargs」に渡して、「test.txt」ファイルをコピーします。

下記の例は「text.txt」が「test_dir1」と「test_dir2」ディレクトリにコピーされます。

$ echo {test_dir1,test_dir2} | xargs -t -n 1 cp -p test.txt
cp -p test.txt test_dir1
cp -p test.txt test_dir2

「test_dir1」と「test_die2」ディレクトリに「test.txt」ファイルがコピーされていることを確認します。

$ ls -lR
.:
total 12
-rw-rw-r-- 1 tamohiko tamohiko    5 Apr  9 11:15 test.txt
drwx------ 2 tamohiko tamohiko 4096 Apr 10 00:21 test_dir1
drwxrwxr-x 2 tamohiko tamohiko 4096 Apr 10 00:21 test_dir2

./test_dir1:
total 4
-rw-rw-r-- 1 tamohiko tamohiko 5 Apr  9 11:15 test.txt

./test_dir2:
total 4
-rw-rw-r-- 1 tamohiko tamohiko 5 Apr  9 11:15 test.txt

こんな書き方もできます。

$ echo test_dir{1,2} | xargs -t -n 1 cp -p test.txt 
cp -p test.txt test_dir1
cp -p test.txt test_dir2

forを使用する方法

bashのforを使用して複数のコピー先をxargsに渡す方法も有ります。

for i in コピー先1 コピー先2; do echo $i; done | xargs -t -n 1 cp -p コピー元

コピー先を増やしたい場合は、スペースで区切って「for i in コピー先1 コピー先2 コピー先3;」といったようにコピー先を追加します。

実行例

forを使用して「test_dir1」と「test_dir2」を「xargs」に渡して、「test.txt」ファイルをコピーします。

$ for i in test_dir1 test_dir2; do echo $i; done | xargs -t -n 1 cp -p test.txt
cp -p test.txt test_dir1
cp -p test.txt test_dir2

whileを使う方法

bashのwhileを使うとバックアップ先を記述したファイルから読み込んで、コピー先を指定することもできます。

$ while read line; do echo "$line"; done < "ファイル" | xargs -t -n 1 cp -p コピー元

実行例

「backup_list.txt」というバックアップ先を記述したファイルを事前に作成しました。

$ cat backup_list.txt 
./test_2.txt
./test_dir1/test.txt
./test_dir2/test.txt

「backup_list.txt」ファイルを読み込んで「text.txt」をコピーします。

$ while read line; do echo "$line"; done < "./backup_list.txt" | xargs -t -n 1 cp -p test.txt 
cp -p test.txt ./test_2.txt
cp -p test.txt ./test_dir1/test.txt
cp -p test.txt ./test_dir2/test.txt

実際に「test.txt」がコピーされていることが確認できます。

$ ls -Rl 
.:
total 20
-rw-rw-r-- 1 tamohiko tamohiko   55 Apr 10 14:42 backup_list.txt
-rw-rw-r-- 1 tamohiko tamohiko    5 Apr  9 11:15 test.txt
-rw-rw-r-- 1 tamohiko tamohiko    5 Apr  9 11:15 test_2.txt
drwx------ 2 tamohiko tamohiko 4096 Apr 10 14:45 test_dir1
drwxrwxr-x 2 tamohiko tamohiko 4096 Apr 10 14:45 test_dir2

./test_dir1:
total 4
-rw-rw-r-- 1 tamohiko tamohiko 5 Apr  9 11:15 test.txt

./test_dir2:
total 4
-rw-rw-r-- 1 tamohiko tamohiko 5 Apr  9 11:15 test.txt

日時をつけてコピーする方法

設定ファイルをコピーしてバックアップを行う場合、コピー先のデータに日時を追加してコピーしたいことがあると思いますので、コピー先に日時を追加する方法も紹介します。

ブレース展開を使用

下記の例だと、コピーした日時をつけたtest.txtを同じフォルダ内とtest_dir2ディレクトリの2箇所にコピーしています。

$ echo {test.txt_$(date +%Y%m%d-%H%M%S),test_dir2/test.txt_$(date +%Y%m%d-%H%M%S)} | xargs -t -n 1 cp -p test.txt 
cp -p test.txt test.txt_20240409-112731
cp -p test.txt test_dir2/test.txt_20240409-112731

forを使用した場合

forを使用する場合はこんな感じになります。

$ for i in test.txt_$(date +%Y%m%d-%H%M%S) test_dir2/test.txt_$(date +%Y%m%d-%H%M%S); do echo $i; done | xargs -t -n 1 cp -p test.txt 
cp -p test.txt test.txt_20240409-114024
cp -p test.txt test_dir2/test.txt_20240409-114024

whileを使用した場合

whileを使用して、バックアップ先をファイルから読み込む場合はこんな感じになります。

$ while read line; do echo "$line"_$(date +%Y%m%d-%H%M%S); done < "./backup_list.txt" | xargs -t -n 1 cp -p test.txt 
cp -p test.txt ./test_2.txt_20240410-145705
cp -p test.txt ./test_dir1/test.txt_20240410-145705
cp -p test.txt ./test_dir2/test.txt_20240410-145705

コメント

タイトルとURLをコピーしました