Can now untar
This commit is contained in:
parent
88ba148efd
commit
3ac0e68275
3 changed files with 81 additions and 55 deletions
33
Cargo.lock
generated
33
Cargo.lock
generated
|
|
@ -230,6 +230,7 @@ dependencies = [
|
|||
"eyre",
|
||||
"indicatif",
|
||||
"rayon",
|
||||
"tar",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -242,6 +243,18 @@ dependencies = [
|
|||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.27.3"
|
||||
|
|
@ -521,6 +534,17 @@ version = "0.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"libc",
|
||||
"xattr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
|
|
@ -759,3 +783,12 @@ name = "windows_x86_64_msvc"
|
|||
version = "0.48.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6ade45bc8bf02ae2aa34a9d54ba660a1a58204da34ba793c00d83ca3730b5f1"
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -12,3 +12,4 @@ crossterm = "0.27.0"
|
|||
eyre = "0.6.8"
|
||||
indicatif = "0.17.6"
|
||||
rayon = "1.7.0"
|
||||
tar = "0.4.40"
|
||||
102
src/main.rs
102
src/main.rs
|
|
@ -1,80 +1,72 @@
|
|||
use clap::{App, Arg};
|
||||
use crossterm::style::{Color, Print, ResetColor, SetForegroundColor,ExecutableCommand};
|
||||
use indicatif::{ProgressBar, ProgressStyle};
|
||||
use std::{io::stdout, path::Path, process::Command};
|
||||
use std::{
|
||||
io,
|
||||
path::Path,
|
||||
fs::{self, File},
|
||||
};
|
||||
use rayon::prelude::*;
|
||||
use tar::Archive;
|
||||
|
||||
fn main() -> color_eyre::eyre::Result<()> {
|
||||
color_eyre::install()?;
|
||||
let app = App::new("extract")
|
||||
.arg(
|
||||
Arg::with_name("files")
|
||||
.required(true)
|
||||
.multiple(true)
|
||||
.help("Files to be extracted"),
|
||||
|
||||
let app = clap::App::new("extract")
|
||||
.arg(
|
||||
clap::Arg::with_name("files")
|
||||
.required(true)
|
||||
.multiple(true)
|
||||
.help("Files to be extracted"),
|
||||
);
|
||||
|
||||
let matches = app.get_matches();
|
||||
let matches = app.get_matches();
|
||||
let files: Vec<_> = matches.values_of("files").unwrap().collect();
|
||||
|
||||
let pb = ProgressBar::new(files.len() as u64);
|
||||
pb.set_style(ProgressStyle::default_bar()
|
||||
.template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})")?
|
||||
.progress_chars("#>-"));
|
||||
pb.set_style(
|
||||
ProgressStyle::default_bar()
|
||||
.template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})")?,
|
||||
);
|
||||
|
||||
files.par_iter().for_each(|file| {
|
||||
if let Err(err) = extract_file(file) {
|
||||
// You can handle the error here, perhaps by printing a message.
|
||||
if let Err(err) = extract_file(file, "output_directory/") {
|
||||
println!("Error extracting file '{}': {}", file, err);
|
||||
}
|
||||
pb.inc(1);
|
||||
});
|
||||
|
||||
|
||||
pb.finish_with_message("All files extracted successfully!");
|
||||
Ok(())
|
||||
}
|
||||
fn extract_tar(file: &str, output_dir: &str) -> color_eyre::eyre::Result<()> {
|
||||
let tar_file = File::open(file)?;
|
||||
let mut a = Archive::new(tar_file);
|
||||
|
||||
fn extract_file(file: &str) -> color_eyre::eyre::Result<()> {
|
||||
if !Path::new(file).exists() {
|
||||
return Err(color_eyre::eyre::eyre!("'{}' - file does not exist", file));
|
||||
}
|
||||
for i in a.entries()? {
|
||||
let mut i = i?;
|
||||
let entry_path = i.header().path()?;
|
||||
let full_path = Path::new(output_dir).join(entry_path);
|
||||
|
||||
let command = match Path::new(file).extension().and_then(|s| s.to_str()) {
|
||||
Some("tar") | Some("tar.gz") | Some("tar.xz") | Some("tbz2") | Some("tgz") | Some("txz") => "tar",
|
||||
Some("lzma") => "unlzma",
|
||||
Some("bz2") => "bunzip2",
|
||||
Some("rar") => "unrar",
|
||||
Some("gz") => "gunzip",
|
||||
Some("zip") => "unzip",
|
||||
Some("z") => "uncompress",
|
||||
Some("7z") | Some("arj") | Some("cab") | Some("chm") | Some("deb") | Some("dmg") | Some("iso") | Some("lzh") | Some("msi") | Some("rpm") | Some("udf") | Some("wim") | Some("xar") => "7z",
|
||||
Some("xz") => "unxz",
|
||||
Some("exe") => "cabextract",
|
||||
_ => {
|
||||
println!("extract: '{}' - unknown archive method", file);
|
||||
return Ok(());
|
||||
if i.header().entry_type().is_dir() {
|
||||
fs::create_dir_all(&full_path)?;
|
||||
} else {
|
||||
fs::create_dir_all(&full_path.parent().unwrap())?;
|
||||
|
||||
let mut file = File::create(&full_path)?;
|
||||
io::copy(&mut i, &mut file)?;
|
||||
}
|
||||
};
|
||||
|
||||
let args = match command {
|
||||
"tar" => vec!["xvf", file],
|
||||
"unrar" => vec!["x", "-ad", file],
|
||||
"7z" => vec!["x", file],
|
||||
_ => vec![file],
|
||||
};
|
||||
|
||||
let output = Command::new(command).args(&args).output()?;
|
||||
|
||||
if !output.status.success() {
|
||||
let mut stdout = stdout();
|
||||
stdout
|
||||
.execute(SetForegroundColor(Color::Red))?
|
||||
.execute(Print(format!(
|
||||
"Failed to extract '{}', command returned error\n",
|
||||
file
|
||||
)))?
|
||||
.execute(ResetColor)?;
|
||||
return Err(eyre::eyre!("Extraction failed for {}", file));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn extract_file(file: &str, output_dir: &str) -> color_eyre::eyre::Result<()> {
|
||||
if !Path::new(file).exists() {
|
||||
return Err(color_eyre::eyre::eyre!("'{}' - file does not exist", file));
|
||||
}
|
||||
if let Some("tar") = Path::new(file).extension().and_then(|s| s.to_str()) {
|
||||
extract_tar(file, output_dir)?;
|
||||
} else {
|
||||
println!("extract: '{}' - unknown archive method", file);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue