zip コマンドで効率的にバックアップ

この記事は約8分で読めます。

Linux の zip コマンドはよく使われるコマンドであり、さまざまなオプションがあります。その中でファイルのバックアップに便利そうなオプションを今回は紹介します。ちょっとググった感じではヒットしなかったのでもしかしたらマイナーなオプションなのかもしれません。

動作確認環境は Ubuntu 20.04.3 LTS です。また、Windows WSL でも動作しました。

スポンサーリンク

基本的な使い方

まず zip のおさらいです。基本的な使い方は簡単です。引数に作成する zip ファイル名と圧縮するファイル名を渡せばOKです。たとえば下記のようなファイルとディレクトリがあったとします。これを全部 zip にかためてバックアップを取ることを考えます。


$ tree
.
├── a.txt
├── b.txt
├── c.txt
└── foo
    ├── fuga.txt
    └── hoge.txt

ここでカレントディレクトリ以下全部を圧縮してみます。下記のように -r(--recurse-paths) の再帰オプションとワイルドカードを組み合わせればできます。また、unzip -l は zip の中のファイル一覧を表示するコマンドです。期待通り全部格納されています。


$ zip  -r backup.zip ./*
  adding: a.txt (stored 0%)
  adding: b.txt (stored 0%)
  adding: c.txt (stored 0%)
  adding: foo/ (stored 0%)
  adding: foo/hoge.txt (stored 0%)
  adding: foo/fuga.txt (stored 0%)
$ unzip -l
Archive:  backup.zip
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2022-02-24 23:24   a.txt
        0  2022-02-24 23:24   b.txt
        0  2022-02-24 23:24   c.txt
        0  2022-02-24 23:25   foo/
        0  2022-02-24 23:24   foo/hoge.txt
        0  2022-02-24 23:25   foo/fuga.txt
---------                     -------
        0                     6 files
スポンサーリンク

変更されたファイルだけ更新する

つぎにファイルが変更されたときのことを考えます。ファイルが変更されたら backup.zip も作り直す必要がありますね。
いったん backup.zip を消して再度 zip してもいいのですが、もしファイルが多かったり大きかったりするとその方法では効率がわるいです。
そこで登場するのが -u (--update)オプションです。-u をつけると、変更されたファイルだけを更新できます。

下記の例では a.txt を変更し、 -u オプションをつけることで zip 内の a.txt だけを更新しています。このとき変更されていない他のファイルは更新されません。これで不要な処理を省けます。
大量のファイルのバックアップを取るときはこのオプションが便利です。


$ zip -r -u backup.zip ./* # backup.zip はなにも更新されない
$ touch a.txt
$ zip -r -u backup.zip ./*  # a.txt が更新されたので backup.zip の a.txt も更新される
updating: a.txt (stored 0%)
スポンサーリンク

削除されたファイルを反映する

上記の -u オプションはファイルを変更したり新規に追加したりした場合は期待通り動作します。しかしファイルが削除された場合には zip を更新しません。
たとえとして、ここでは a.txt 不要になったとしてファイルを削除した場合を考えてみます。
この状態で上述の -u オプションを使っても backup.zip からは a.txt は削除されません。つまりファイルの状態と zip 内の状態が不一致になってしまいます。

backup.zip からも削除したい場合は -d(–delte)オプションを使うことで backup.zip 内からファイルを削除できます。
ですがこの場合はいちいち削除されたファイルを指定する必要があり、ファイル数が多い場合には漏れが出るかもしれません。

そこで今回は --filesync オプションを使います。これは名前の通り自動的にファイルの状態を同期してくれます。a.txt がs削除された状態で --filesync を使うと backup.zip から自動で a.txt を削除してくれます。
下記の例には書いていませんが、ファイル更新があればもちろん -u と同じように zip 内のファイルも更新します。
バックアップを取るという目的ならこちらのほうが便利かと思います。


$ rm -r a.txt
$ zip -r -u backup.zip ./* # a.txt が削除されても test.zip はなにも更新されない
$ zip -r --filesync backup.zip ./* # a.txt が削除されているので backup.zip からも a.txt が削除される
deleting: a.txt
スポンサーリンク

zipのなかにディレクトリを作りたくない場合

オプション -r でサブディレクトリごと圧縮した場合は、ディレクトリ構成を保持したまま圧縮されます。 下記の例では foo ディレクトリごと圧縮されています。


$ zipinfo backup.zip
Archive:  backup.zip
Zip file size: 876 bytes, number of entries: 6
-rw-r--r--  3.0 unx        0 bx stor 25-Jun-12 10:43 a.txt
-rw-r--r--  3.0 unx        0 bx stor 25-Jun-12 10:31 b.txt
-rw-r--r--  3.0 unx        0 bx stor 25-Jun-12 10:31 c.txt
drwxr-xr-x  3.0 unx        0 bx stor 25-Jun-12 10:32 foo/
-rw-r--r--  3.0 unx        0 bx stor 25-Jun-12 10:32 foo/fuga.txt
-rw-r--r--  3.0 unx        0 bx stor 25-Jun-12 10:32 foo/hoge.txt
6 files, 0 bytes uncompressed, 0 bytes compressed:  0.0%

もしディレクトリを含めたくない、サブディレクトリ以下のファイル含めてすべてのファイルがトップにある状態で圧縮したい場合は –junk-paths オプションが有用です。
下記の例では –junk-pathsを使って圧縮した場合、 fooディレクトリ自体は含まれず、そのfooディレクトリの下にあったfuga.txt, hoge.txtハッシュ腐れています。


$ zip --junk-paths -r --latest-time --must-match --filesync backup.zip ./
$ zipinfo backup.zip
Archive:  backup.zip
Zip file size: 724 bytes, number of entries: 5
-rw-r--r--  3.0 unx        0 bx stor 25-Jun-12 10:43 a.txt
-rw-r--r--  3.0 unx        0 bx stor 25-Jun-12 10:31 b.txt
-rw-r--r--  3.0 unx        0 bx stor 25-Jun-12 10:31 c.txt
-rw-r--r--  3.0 unx        0 bx stor 25-Jun-12 10:32 fuga.txt
-rw-r--r--  3.0 unx        0 bx stor 25-Jun-12 10:32 hoge.txt
5 files, 0 bytes uncompressed, 0 bytes compressed:  0.0%
スポンサーリンク

うっかり意図しないファイルを圧縮するのを防ぐ

zip コマンドに存在しないファイルを指定してもエラーにはなりません。Warningが出るのみです。うっかりファイル名を間違えてもエラーにならないので少し危ないです。


$ zip -r --filesync backup.zip ./ none.txt
zip warning: name not matched: none.txt
Archive is current

予めファイル名がわかっているときは –must-match オプションが有用です。指定したファイルが見当たらないときはWarningではなくエラーにしてくれます。


$ zip -r --must-match --filesync backup.zip ./ none.txt
zip warning: name not matched: none.txt
zip I/O error: No such file or directory
zip error: File not found or no read permission (none.txt)
/code>

ワイルドカードを使う場合はもちろん効果が弱まるのでご注意を。

スポンサーリンク

まとめ

今回はファイルバックアップに便利な zip の --filesync オプションを紹介しました。ググってもこのオプションはあんまりヒットしないようなので、詳細は man zip で確認するのがいいかと思います。

コメント