Working with Tarballs
Decompress a tarball
Decompress (GzDecoder) and
extract (Archive::unpack) all files from a compressed tarball
named archive.tar.gz located in the current working directory
to the same location.
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(()) }
Compress a directory into tarball
Compress /var/log directory into archive.tar.gz.
Creates a File wrapped in GzEncoder
and tar::Builder. Adds contents of /var/log directory recursively into the archive
under backup/logs path with Builder::append_dir_all.
GzEncoder is responsible for transparently compressing the
data prior to writing it into 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(()) }
To add the contents without renaming them, an empty string can be used as the first argument of Builder::append_dir_all:
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(()) }
The default behavior of tar::Builder differs from the GNU tar utility's defaults tar(1),
notably tar::Builder::follow_symlinks(true) is the equivalent of tar --dereference.
Decompress a tarball while removing a prefix from the paths
Iterate over the Archive::entries. Use Path::strip_prefix to remove
the specified path prefix (bundle/logs). Finally, extract the tar::Entry
via Entry::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(()) }