January 3, 2023

cpコマンドで1つのソースを複数の宛先にコピー

あるディレクトリを、中身はそのまま複数のディレクトリにコピーしたい時とかに

cpコマンドは、

  • 1つのSOURCE(ファイルまたはディレクトリ)を1つのDEST(ファイルまたはディレクトリ)にコピー
  • 複数のSOURCEファイルを1つのDESTディレクトリにコピー

はできるけど、

  • 1つのSOURCE(ファイルまたはディレクトリ)を複数のDEST(ファイルまたはディレクトリ)にコピー

はできない。

cpコマンド単体ではできないけど、Bashのブレース展開とxargsコマンドを使えば実現できる。
例えば、testというディレクトリを、test01からtest10までの10個にコピーしたい時はこんな感じ。

$ echo test{01..10} | xargs -n 1 cp -a test

ちなみにブレース展開は レースじゃなくて レース、英語表記はBrace Expansion

ブレース展開はechoコマンドに限らず色々使える

$ export {http,https,ftp}_proxy=http://192.168.100.40:8080
$ env | grep proxy
http_proxy=http://192.168.100.40:8080
ftp_proxy=http://192.168.100.40:8080
https_proxy=http://192.168.100.40:8080
$ mkdir /tmp/test{01..10}
$ ls -d /tmp/test*
/tmp/test01  /tmp/test03  /tmp/test05  /tmp/test07  /tmp/test09
/tmp/test02  /tmp/test04  /tmp/test06  /tmp/test08  /tmp/test10
$ rm -rf /tmp/test{03,05,06,08,10}
$ ls -d /tmp/test*
/tmp/test01  /tmp/test02  /tmp/test04  /tmp/test07  /tmp/test09

ブレース展開とは?

『ブレース(中括弧)』の中に書いたものが、コマンド実行時に文字列として『展開』される仕組み。
中括弧の中はカンマ区切り文字列、またはシーケンス式で、文字または整数が使える。

$ echo {a,d,c}
a d c
$ echo {1,5,3}
1 5 3
$ echo {A..E}
A B C D E
$ echo {a..e}
a b c d e
$ echo {1..5}
1 2 3 4 5

Aからzの間はこんな感じ

$ echo {A..z}
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [  ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z

カンマ区切りは文字と数字を区別しないし文字列も使える

$ echo {10,a,2,Z,hoge,fuga}
10 a 2 Z hoge fuga

数字は頭に0を付けるとゼロパディングする

$ echo {01..05}
01 02 03 04 05

オプションとして、中括弧の前にプリアンブル、中括弧の後にポストスクリプトを付けることもできる。

$ echo pre-{1..5}-post
pre-1-post pre-2-post pre-3-post pre-4-post pre-5-post

GNU bash, version 4以降ならシーケンス式の中でインクリメントも指定できる。

$ echo {0..9..1}
0 1 2 3 4 5 6 7 8 9
$ echo {0..9..2}
0 2 4 6 8
$ echo {0..9..3}
0 3 6 9

※CentOS 5まではbash version 3だけど、CentOS 6以降はbash version 4だから、ほとんどの環境ではインクリメント指定できるはず

$ cat /etc/redhat-release
CentOS release 5.11 (Final)
$ bash --version
GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.
$ echo {1..9}
1 2 3 4 5 6 7 8 9
$ echo {1..9..2}
{1..9..2}
$ cat /etc/redhat-release
CentOS release 6.10 (Final)
$ bash --version
GNU bash, version 4.1.2(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ echo {1..9}
1 2 3 4 5 6 7 8 9
$ echo {1..9..2}
1 3 5 7 9
$ cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
$ bash --version
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ echo {1..9}
1 2 3 4 5 6 7 8 9
$ echo {1..9..2}
1 3 5 7 9

© 2020 nissy-lab.com