地味に便利だけどあまり知られていない気がするBraceExpansionを紹介するぜ!
BraceExpansionって?
{
,}
で囲うとその要素の数だけコマンドを複数実行できるのだ
$ echo {k,c}atherine
katherine catherine
PS3のキャサリンおもしろいよね
例
例えば複数ファイルを作成したりできる
$ echo {Main,Person,Group}.java # echoで確認
Main.java Person.java Group.java
$ touch {Main,Person,Group}.java
$ ls
Group.java Main.java Person.java
複数書いたら全組み合わせ展開される
$ mkdir -p {src,test}/main/java/xxx/{api,service,db}
$ tree --charset=C
.
|-- src
| `-- main
| `-- java
| `-- xxx
| |-- api
| |-- db
| `-- service
`-- test
`-- main
`-- java
`-- xxx
|-- api
|-- db
`-- service
ディレクトリの切れ目じゃあなくても当然おk
$ touch {Person,Group}_{Create,Update,Delete}_Api.java
$ ls
Group_Create_Api.java Group_Delete_Api.java Group_Update_Api.java Person_Create_Api.java Person_Delete_Api.java Person_Update_Api.java
連続要素も展開できる
$ touch testdata_{1..5}
$ ls
testdata_1 testdata_2 testdata_3 testdata_4 testdata_5
$ touch dir_{A..E}
$ ls
dir_A dir_B dir_C dir_D dir_E
(何故かアルファベットの方はzshでは展開されなかったので、上記の例はbash)
ネストもできる
$ mkdir -p api/{person/{get,post},group/{post,put,delete}}
$ tree --charset=C
.
`-- api
|-- group
| |-- delete
| |-- post
| `-- put
`-- person
|-- get
`-- post
mkdirばっかりじゃあなくて消したり
$ touch {1..3}.{java,class,log,bk,test} # サンプル用意
$ ls -l
1.bk
1.class
1.java
1.log
1.test
2.bk
2.class
2.java
2.log
2.test
3.bk
3.class
3.java
3.log
3.test
$ rm *.{log,bk}
$ ls -l
1.class
1.java
1.test
2.class
2.java
2.test
3.class
3.java
3.test
探したりもできるよ
$ mkdir {src,test,tool,doc}
$ touch {src,test,tool,doc}/{1..3}.{java,class} # サンプル準備
$ tree --charset=C
.
|-- doc
| |-- 1.class
| |-- 1.java
| |-- 2.class
| |-- 2.java
| |-- 3.class
| `-- 3.java
|-- src
| |-- 1.class
| |-- 1.java
| |-- 2.class
| |-- 2.java
| |-- 3.class
| `-- 3.java
|-- test
| |-- 1.class
| |-- 1.java
| |-- 2.class
| |-- 2.java
| |-- 3.class
| `-- 3.java
`-- tool
|-- 1.class
|-- 1.java
|-- 2.class
|-- 2.java
|-- 3.class
`-- 3.java
$ find {src,test} -name "2.*"
src/2.class
src/2.java
test/2.class
test/2.java
特にこの複数箇所を探すのはfor
使ったりxargs
使ったり、1つずつ実行して上キーでちょい改変したりするよりはずっと楽だよ!
おまけ (たぶんzsh)
実行前に展開
zshはglob展開がTab
で出来るけど、BraceExpansionでも有効
$ touch {1..3}.{java,class,log,bk,test} # サンプル準備
$ rm *.{log,bk} # ここでTab
$ rm 1.log 2.log 3.log 1.bk 2.bk 3.bk # 当然、条件に合う要素のみ
rm系とかは実行前に展開して消しすぎないか確認する癖を付けるのが大事!
展開のUndo
$ rm *.{log,bk} # ここでTab
$ rm 1.log 2.log 3.log 1.bk 2.bk 3.bk # ここでctrl-x,u
$ rm *.{log,bk} # 戻る
展開せずに結果をチラ見
$ echo 201{5,6}-{01..12} # ここでctrl-x,g
$ echo 201{5,6}-{01..12}
2015-01 2015-03 2015-05 2015-07 2015-09 2015-11 2016-01 2016-03 2016-05 2016-07 2016-09 2016-11
2015-02 2015-04 2015-06 2015-08 2015-10 2015-12 2016-02 2016-04 2016-06 2016-08 2016-10 2016-12
こっちの方は複雑なコマンドを結果を見ながらちょい改変したりに向いている
いじょーー!