2015年02月16日
tarコマンドで、コマンドラインの文字数制限に悩まず再帰的にファイルをコピーする
Ubuntu 14.04 64bit で実行される、とあるプロダクトのビルドスクリプトの一部で、大量にファイルが存在するディレクトリを cp -r * でアーカイブしようとした所、一部のファイルがコピーされないという現象に悩みました。当初は HDD やファイルシステムの障害を疑ったりもしたのですが、結局は bash によりワイルドカードが展開され、cp に渡されたコマンドライン引数が長すぎて、途中で切れていたのが原因のようです。(エラーが何も出ないのが不思議なのですが…。)
このような場合は、find と xargs を使うのが定番のようですが、この時は絶対パスでディレクトリを扱っていたので、都合良く特定のディレクトリ以下の構造を保ったまま cp コマンドでコピーする方法がわからず※、あれこれ試行錯誤したあげく、結局 tar を使ってコピーしました。以下のようにして、AAA 以下の大量のファイルを BBB 以下に再帰的にコピーできました。
※ --parents オプションでは、絶対パスの先頭からのディレクトリ構造でコピーされてしまいました。
$ tar -C /path/to/AAA -chf - . | tar -xf - -C /path/to/BBBC オプションでディレクトリを移動、h オプションでシンボリックリンクを辿ります。c は圧縮、x は展開、f でファイル名指定。今回は - で標準入出力を指定しています。(ちなみに、もともとの cp -r /path/to/AAA/* /path/to/BBB/ を書き換えやすいように、-C を両端に寄せているので、オプションの並びがちょっと変則的になっています。)
※ --parents オプションでは、絶対パスの先頭からのディレクトリ構造でコピーされてしまいました。