1. 使用 tar
包
需要安装flate2
和tar
库,可通过cargo add flate2
和cargo add tar
命令安装
[dependencies] flate2 = "1.0.25" tar = "0.4.38"
|
1.1 压缩目录为 tar
包
压缩 /root/testtar
目录内的内容到 archive.tar.gz
压缩包中。创建一个用 GzEncoder
和 tar::Builder
包裹的 File
。使用 Builder::append_dir_all
,将 /root/testtar
目录内的内容递归添加到 backup/code
路径下的归档文件中。在将数据写入压缩包 archive.tar.gz
之前,GzEncoder
负责清晰地将数据压缩。
/root/testtar/ ├── Cargo.lock_copy ├── Cargo.toml_copy └── src-rust └── main.rs
|
use flate2::write::GzEncoder; use flate2::Compression; use std::fs::File; use tar::Builder;
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 = Builder::new(enc); tar.append_dir_all("backup/code", "/root/testtar")?; Ok(()) }
|
- 运行命令如下,在当前目录下生成一个名为
archive.tar.gz
的压缩包
├── Cargo.lock ├── Cargo.toml ├── archive.tar.gz ├── src │ └── main.rs └── target
|
1.2. 解压 tar
包
从当前工作目录中的压缩包 archive.tar.gz
,解压(GzDecoder
)和提取(Archive::unpack
)所有文件,并放在copy
目录下。
use flate2::read::GzDecoder; use std::fs::File; 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("./copy/")?;
Ok(()) }
|
- 目录结构如下,可以看到目录包含
backup/code
copy/ └── backup └── code ├── Cargo.lock_copy ├── Cargo.toml_copy └── src-rust └── main.rs
|
1.3 从路径移除前缀时,解压 tar
包
循环遍历 Archive::entries
。使用 Path::strip_prefix
移除指定的路径前缀(bundle/logs)。最终,通过 Entry::unpack
提取 tar::Entry
(tar
包中的内容)。此块代码需要安装error-chain
库,通过error-chain
命令安装
[dependencies] error-chain = "0.12.4" flate2 = "1.0.25" tar = "0.4.38"
|
use error_chain::error_chain; use flate2::read::GzDecoder; use std::fs::File; use std::path::PathBuf; use tar::Archive;
error_chain! { foreign_links { Io(std::io::Error); StripPrefixError(::std::path::StripPrefixError); } }
fn main() -> Result<()> { let file = File::open("archive.tar.gz")?; let mut archive = Archive::new(GzDecoder::new(file)); let prefix = "backup/code";
println!("提取了以下文件:"); archive .entries()? .filter_map(|e| e.ok()) .map(|mut entry| -> Result<PathBuf> { 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(()) }
|
提取了以下文件: > src-rust > src-rust/main.rs > Cargo.lock_copy > Cargo.toml_copy
|
├── Cargo.lock_copy ├── Cargo.toml_copy ├── src-rust │ └── main.rs
|