Can now untar

This commit is contained in:
specCon18 2023-08-30 11:37:18 -04:00
parent 88ba148efd
commit 3ac0e68275
3 changed files with 81 additions and 55 deletions

33
Cargo.lock generated
View file

@ -230,6 +230,7 @@ dependencies = [
"eyre", "eyre",
"indicatif", "indicatif",
"rayon", "rayon",
"tar",
] ]
[[package]] [[package]]
@ -242,6 +243,18 @@ dependencies = [
"once_cell", "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]] [[package]]
name = "gimli" name = "gimli"
version = "0.27.3" version = "0.27.3"
@ -521,6 +534,17 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 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]] [[package]]
name = "textwrap" name = "textwrap"
version = "0.11.0" version = "0.11.0"
@ -759,3 +783,12 @@ name = "windows_x86_64_msvc"
version = "0.48.3" version = "0.48.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6ade45bc8bf02ae2aa34a9d54ba660a1a58204da34ba793c00d83ca3730b5f1" checksum = "b6ade45bc8bf02ae2aa34a9d54ba660a1a58204da34ba793c00d83ca3730b5f1"
[[package]]
name = "xattr"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985"
dependencies = [
"libc",
]

View file

@ -12,3 +12,4 @@ crossterm = "0.27.0"
eyre = "0.6.8" eyre = "0.6.8"
indicatif = "0.17.6" indicatif = "0.17.6"
rayon = "1.7.0" rayon = "1.7.0"
tar = "0.4.40"

View file

@ -1,80 +1,72 @@
use clap::{App, Arg};
use crossterm::style::{Color, Print, ResetColor, SetForegroundColor,ExecutableCommand};
use indicatif::{ProgressBar, ProgressStyle}; 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<()> { fn main() -> color_eyre::eyre::Result<()> {
color_eyre::install()?; color_eyre::install()?;
let app = App::new("extract")
.arg( let app = clap::App::new("extract")
Arg::with_name("files") .arg(
.required(true) clap::Arg::with_name("files")
.multiple(true) .required(true)
.help("Files to be extracted"), .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 files: Vec<_> = matches.values_of("files").unwrap().collect();
let pb = ProgressBar::new(files.len() as u64); let pb = ProgressBar::new(files.len() as u64);
pb.set_style(ProgressStyle::default_bar() pb.set_style(
.template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})")? ProgressStyle::default_bar()
.progress_chars("#>-")); .template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})")?,
);
files.par_iter().for_each(|file| { files.par_iter().for_each(|file| {
if let Err(err) = extract_file(file) { if let Err(err) = extract_file(file, "output_directory/") {
// You can handle the error here, perhaps by printing a message.
println!("Error extracting file '{}': {}", file, err); println!("Error extracting file '{}': {}", file, err);
} }
pb.inc(1); pb.inc(1);
}); });
pb.finish_with_message("All files extracted successfully!"); pb.finish_with_message("All files extracted successfully!");
Ok(()) 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<()> { for i in a.entries()? {
if !Path::new(file).exists() { let mut i = i?;
return Err(color_eyre::eyre::eyre!("'{}' - file does not exist", file)); 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()) { if i.header().entry_type().is_dir() {
Some("tar") | Some("tar.gz") | Some("tar.xz") | Some("tbz2") | Some("tgz") | Some("txz") => "tar", fs::create_dir_all(&full_path)?;
Some("lzma") => "unlzma", } else {
Some("bz2") => "bunzip2", fs::create_dir_all(&full_path.parent().unwrap())?;
Some("rar") => "unrar",
Some("gz") => "gunzip", let mut file = File::create(&full_path)?;
Some("zip") => "unzip", io::copy(&mut i, &mut file)?;
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(());
} }
};
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(()) 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(())
}