findを使って、サイズが0バイトでないファイルのみを探して圧縮する
不要になったサーバを削除する前にバックアップを取ろうとしているのですが、その際に少しでもバックアップの容量を削減しようとして調べてみたところ、容量を喰っている大部分がログファイルであることがわかりました。
もう消してしまってもいいようなものですが、念の為出来るだけ圧縮して取っておくことにします。
その際、サイズが0バイトのファイルを圧縮すると却って容量が増えるので(微々たるものですが)、サイズが0バイトのファイルだけは対象から除外することにします。
このように、「与えられた検索条件に従って、指定したディレクトリより下にあるファイルを再帰的に検索する」必要がある時に使うコマンドと言えば、 find です。find を使えば、ファイルのメタデータ1を条件にしたありとあらゆる検索が出来るのですが、今回はあまり知られていないであろう -size オプションを取り上げてみます。
実行したコマンド(find, xargs, bzip2)
実際に実行したコマンドは次のようなものです。
find . -name '*.log' -size +1c | xargs bzip2
言葉で説明すると、
カレントディレクトリの下にある、
ファイル名が .log で終わり、
サイズが1バイト以上のファイルを検索し、
bzip2で圧縮する
となるのですが、コマンド1つ1つを詳しく説明して行くことにしましょう。
find
find を使えば、ファイルのメタデータ1を条件にしたありとあらゆる検索が出来るのですが、
今回は下記2つのオプションを使います。
- -name パターン
- ファイル名(パスの最後の部分)が与えられたパターンにマッチしたファイルのみを表示する。
上記の例の場合、ファイル名が “.log” で終わっているファイルのみがマッチする。 - -size 条件
-
与えられた条件にマッチしたファイルのみを表示する。条件は下記のフォーマットで指定する。
[+/-]N[unit]
先頭に付けた +/- の意味は下記の通り。
- +N
- N以上
- -N
- N以下
- N
-
ちょうどN
unitはサイズの単位。下記の単位が指定可能。
- c
- バイト
- k
- キロバイト
- M
- メガバイト
- G
-
ギガバイト
セクションの最初に上げた例は「1バイト以上」となる。
[追記(4/13)] 「何で “c” でバイトなの?」って質問があったのですが、FreeBSDのmanページによると、
-size n[ckMGTP]
True if the file’s size, rounded up, in 512-byte blocks is n. If n is followed by a c, then the primary is true if the file’s size is n bytes (characters).
とあるので、bytesというかcharactersを意図しているようです。まぁ、ASCIIなら bytes == characters は成り立つし、find に -size オプションが実装された頃にマルチバイト文字なんて考慮されてなかっただろうと考えると、そんなものかなぁと。
ちなみに Linux (CentOS) の man には特に記述はありませんでした。
xargs
find . -name '*.log' -size +1c
を実行した結果として、
./app/tmp/logs/error.log.1393557679
./app/tmp/logs/error.log.1397188807
./app/tmp/logs/error.log.1393472610
./app/tmp/logs/error.log
という出力が得られるとします。
この結果を bzip2 コマンドに渡し、対象ファイルを圧縮したいのですが、このような時は xargs コマンドを使います。
今回の例の場合、
find . -name '*.log' -size +1c | xargs bzip2
を実行すると、
bzip2 ./app/tmp/logs/error.log.1393557679 ./app/tmp/logs/error.log.1397188807 ./app/tmp/logs/error.log.1393472610 ./app/tmp/logs/error.log
を実行するのと同じことになります。
環境(OS)
今回の例は CentOS 6 で実行しました。
manページを見たところ、macOS の find でも同じオプションが使えるようです。
あまりOS依存のオプションは使っていないと思うので、他のUNIX系OSでも動くのではないかと思います(未確認)。