背景
普段ファイルをzip圧縮したい時は、コマンドラインから下記の様に処理していました。
# テキストファイルsample01.txtをsample01.zipに圧縮
$ zip sample01.zip sample01.txt
しかし、この処理を大量のファイルに対して圧縮及び採番するとなるとあまりにも面倒(というか非現実的)な為、bashでforループ回せないかな?と思って調べたことをメモります。
bashでforループ
まずはbash上でのforループの構文を確認。
$ for 変数 in 値リスト
> do
> なんか処理
> done
となります。意外とシンプル。
例えば、forループお決まりの0から9までの数字を出力する例だと
$ for i in 0 1 2 3 4 5 6 7 8 9
> do
> echo $i
> done
もしくは
$ for i in `seq 0 9`
> do
> echo $i
> done
0
1
2
3
4
5
6
7
8
9
となります。
sample01.txt ~ sample50.txtを1つずつzip圧縮
さて、本題に入ります。
連番で名前が付いているファイルを1つずつ圧縮するには上記のfor文を使うのですが、桁数の都合上01から09までと10から50までの処理を分ける必要があります。
ifで分岐して処理しても良いのですが、そんなにしょっちゅう使うものでもないしなぁ、ということでご容赦下さい。以下のように書きます。
※他に何か良い方法があれば是非教えて下さい!
$ for i in `seq 1 9`
> do
> zip sample0$i.zip sample0$i.txt
> done
$ for i in `seq 10 50`
> do
> zip sample$i.zip sample$i.txt
> done
これでsample01.zip ~ sample50.zipが作成されているはずです!
2020/02/23追記:1回の処理で圧縮する!
@kkdd さんにアドバイス頂き、以下のコマンドで一括で処理できるようになりました!
ありがとうございました!
$ find . -maxdepth 1 -name "*.txt" | sed s/.txt// | xargs -P8 -I% sh -c 'zip -r %.zip %.txt'
処理の解説ですが、
find . -maxdepth 1 -name "*.txt"
で今いるディレクトリ内でファイル名が".txt"で終わるファイルを検索し、その出力結果を
sed s/.txt//
に渡すことで、それぞれのファイル名から.txtという文字列を削除し、最後に
xargs -P8 -I% sh -c 'zip -r %.zip %.txt'
で渡されたファイル名を1つずつzipコマンドの引数に入れて処理をします。
findコマンドの-nameオプションで指定するファイル名は、同ディレクトリ内に他に.txtファイルが存在する場合は、"sample*"等に修正することで対応できますね。