このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

これは便利、tarを使ってファイルをコピーする

バタリアンのタールマンが出てきてしまったわけですが*1、tarのmanページで何を調べていたかっていうと、ファイル抽出(extract)時に新ファイルを上書きしないオプションとか、なにやら。


ファイルのコピーというと、cp, copy, xcopyなどのコマンドを多く使うでしょうが、tarコマンドもファイルコピーに使えます。なかなか便利ですよ。Unix/Linux/Cygwin/MSYS などで GNU tar を使う場合の話です。

一番基本的なのは、カレントディレクトリにあるファイルをすべて再帰的にたどって宛先(destination)ディレクトリにコピーする方法です。

$ tar cf - . | (cd ../dest/; tar xvf -)

ハイフン1文字「-」は標準入出力を表します。出力のときは「f - 」の代わりに -O(または --to-stdout)オプションが使えます。また、ディレクトリの移動をサブシェルで行わなくても -C(または --directory DIR)オプションで出来ます。ですから、次のコマンドラインでも同じ。

$ tar cO . | tar xvf - -C ../dest/

コピーすべきファイルとディレクトリをコマンドラインに指定することもできます。

$ tar cO *.txt index.html lib/ | tar xvf - -C ../dest/

除外するファイルを指定する方法は次のエントリーに書いてあります。

コピーすべきファイルをfindで列挙する場合はxargsと組み合わせます。

$ find . -name '*.txt' -or -name '*.wiki' | xargs tar cO  | tar xvf - -C ../dest/

findでは、ワイルドカード(glob)以外に正規表現パターン(-regex オプション)だの、ファイルのタイムスタンプを目安にした検索(-mtime オプションなど)が使えるので、コピーするファイルの絞り込みに便利です*2。ファイル名に空白を含む場合の対処は次のエントリーを見てください。

コピーすべきファイル群に規則性がないときは、しょうがないので個別のファイル名を全部列挙するしかないですね。そのとき、コマンドラインにファイル名を並べるのは大変なので、files.list とかいうファイルを作ります。そして、次のように --files-from オプションを使います。

$ tar cO --files-from files.list | tar xvf - -C ../dest/

files.list には、1行に1ファイルずつファイル名(パス)を書き連ねます。

宛先にあるファイルが新しいときに上書きしたくないならば、--keep-newer-files を使います。

$ tar cO . | tar xvf - --keep-newer-files -C ../dest/

-v(または --verbose)オプションのメッセージを取っておきたいとき、リダイレクトやteeコマンドを使ってもいいですが、--index-fileオプションが使えます。

$ tar cO . | tar xvf - --keep-newer-files -C ../dest/ --index-file tar.out

*1:tar man を tarman とするとタールマンが出てきますが、make man を makemanとすると沖縄のホームセンター「メイクマン」が引っかかります。http://www.makeman.co.jp/

*2:findの -regex, -mtime は間違いやすいので、マニュアルをよく読んでから使ってください。