はじめに
こんにちは、酸素です。
先日、Linuxのブレース展開という機能について知る機会があったので、今回はそれを紹介していきます。
経緯
ある日、いつものようにログ調査をしていると、先輩から以下のようなファイルの指定方法を教えていただきました。
$ zcat log.[1-9].gz
弊社のサーバーでは、一定期間のログをgz形式で圧縮しローテートしているため、
上記のコマンドを実行するとlog.1、log.2、....log.9.gzと1~9までのログファイルを一括で指定することができます。
これで無事に業務が捗ると良い話で終わったのですが、(ブログ的には薄味?)
下記のように2桁以上のファイルを指定した時、明らかに出力の量が少ないことがありました。
$ zcat log.[1-20].gz
最初は気のせいかと思ったのですが、findコマンドで同様の指定をすると、確かに少ないことが分かりました。
$ find log.[1-20].gz
log.1.gz
log.2.gz
原因
調べたところ、[]でファイル名を指定する方法はglobと呼ばれるパターンマッチングで、GNU Bash manualに詳細な仕様が記載されていました。
GNU Bash manualによると、[]内でハイフンを使った範囲指定は、ハイフンの前後1文字に対して解決するため、[1-20]という指定方法では上手く抽出できなかったとのことでした。
また、余談ですが[]内でハイフンを使った範囲指定は、アルファベットも解決でき、[a-d]のように指定することでa,b,c,dのいずれかを含む文字列を抽出できます。
解決方法
では、当初行いたかった1~20のファイルを抽出する方法について考えていきます。
幾つかの方法はあるかと思いますが、今回はglobと同様、linuxのbashにて実装されているBrace Expansion(ブレース展開)という機能を利用してみます。
ブレース展開は{}内に使って指定したい条件を入れることで文字列を抽出できます。
また、範囲指定をする際は、ハイフンではなく{x..y}のようにピリオド2つで表現します。
この時のx,yは内部的には数値として解決されるため桁数に関係なく範囲指定が可能となっております。
実際に試してみると、上手く指定ができました!
$ find log.{1..20}.gz
log.1.gz
log.2.gz
log.3.gz
(省略)
log.18.gz
log.19.gz
log.20.gz
まとめ
ブレース展開を利用して、自在にファイルを指定することができました。
また、GNU bash manualには、様々なbashの機能の仕様が記載されているので、
日々利用しているコマンドの豆知識を知ることができ楽しかったです!