Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Tarball の操作

tarball を展開する

flate2-badge tar-badge cat-compression-badge

圧縮 tarball を解凍し(GzDecoder)、 現在の作業ディレクトリにある archive.tar.gz という名前の すべてのファイルを展開します(Archive::unpack)。 展開先は同じ場所です。

use std::fs::File;
use flate2::read::GzDecoder;
use tar::Archive;

fn main() -> Result<(), std::io::Error> {
    let path = "archive.tar.gz";

    let tar_gz = File::open(path)?;
    let tar = GzDecoder::new(tar_gz);
    let mut archive = Archive::new(tar);
    archive.unpack(".")?;

    Ok(())
}

ディレクトリを tarball に圧縮する

flate2-badge tar-badge cat-compression-badge

/var/log ディレクトリを archive.tar.gz に圧縮します。

GzEncoder および tar::Builder でラップされた File を作成します。

Builder::append_dir_all を使用して、/var/log ディレクトリの内容を backup/logs パスの下に再帰的にアーカイブへ追加します。 GzEncoder は、データを archive.tar.gz に書き込む前に透過的に圧縮する役割を担います。

use std::fs::File;
use flate2::Compression;
use flate2::write::GzEncoder;

fn main() -> Result<(), std::io::Error> {
    let tar_gz = File::create("archive.tar.gz")?;
    let enc = GzEncoder::new(tar_gz, Compression::default());
    let mut tar = tar::Builder::new(enc);
    tar.append_dir_all("backup/logs", "/var/log")?;
    tar.finish()?;
    Ok(())
}

内容の名前を変更せずに追加するには、Builder::append_dir_all の第 1 引数に空文字列を使用できます:

use std::fs::File;
use flate2::Compression;
use flate2::write::GzEncoder;

fn main() -> Result<(), std::io::Error> {
    let tar_gz = File::create("archive.tar.gz")?;
    let enc = GzEncoder::new(tar_gz, Compression::default());
    let mut tar = tar::Builder::new(enc);
    tar.append_dir_all("", "/var/log")?;
    tar.finish()?;
    Ok(())
}

tar::Builder のデフォルトの挙動は、GNU tar ユーティリティのデフォルト tar(1) とは異なります。 特に、tar::Builder::follow_symlinks(true)tar --dereference と同等です。

パスからプレフィックスを削除しながら tarball を展開する

flate2-badge tar-badge cat-compression-badge

Archive::entries を反復処理します。 Path::strip_prefix を使って、 指定したパスプレフィックス(bundle/logs)を削除します。最後に、 tar::EntryEntry::unpack で展開します。

use anyhow::Result;
use std::fs::File;
use std::path::PathBuf;
use flate2::read::GzDecoder;
use tar::Archive;

fn main() -> Result<()> {
    let file = File::open("archive.tar.gz")?;
    let mut archive = Archive::new(GzDecoder::new(file));
    let prefix = "bundle/logs";

    println!("Extracted the following files:");
    archive
        .entries()?
        .filter_map(|e| e.ok())
        .map(|mut entry| -> Result<PathBuf, Box<dyn std::error::Error>> {
            let path = entry.path()?.strip_prefix(prefix)?.to_owned();
            entry.unpack(&path)?;
            Ok(path)
        })
        .filter_map(|e| e.ok())
        .for_each(|x| println!("> {}", x.display()));

    Ok(())
}