Working with Tarballs
Decompress a tarball
Decompress (GzDecoder
) andextract (Archive::unpack
) all files from a compressed tarballnamedarchive.tar.gz
located in the current working directoryto 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 intoarchive.tar.gz
.
Creates aFile
wrapped inGzEncoder
andtar::Builder
.Adds contents of/var/log
directory recursively into the archiveunderbackup/logs
path withBuilder::append_dir_all
.GzEncoder
is responsible for transparently compressing thedata prior to writing it intoarchive.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 ofBuilder::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 oftar::Builder
differs from the GNUtar
utility's defaultstar(1),notablytar::Builder::follow_symlinks(true)
is the equivalent oftar --dereference
.
Decompress a tarball while removing a prefix from the paths
Iterate over theArchive::entries
. UsePath::strip_prefix
to removethe specified path prefix (bundle/logs
). Finally, extract thetar::Entry
viaEntry::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(())}