refactored
This commit is contained in:
parent
982ee2b239
commit
23d8a8d914
7 changed files with 653 additions and 128 deletions
121
src/extractors.rs
Normal file
121
src/extractors.rs
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
use std::{fs, io, path::Path};
|
||||
use unrar::Archive;
|
||||
use xz2::bufread::XzDecoder;
|
||||
|
||||
// pub fn extract_xz(xz_file: &Path) -> io::Result<()> {
|
||||
// let file = fs::File::open(xz_file)?;
|
||||
// let decompressor = XzDecoder::new(file);
|
||||
// let mut archive = tar::Archive::new(decompressor);
|
||||
|
||||
// for entry in archive.entries()? {
|
||||
// let mut entry = entry?;
|
||||
|
||||
// let entry_path = entry.path()?;
|
||||
// let full_path = Path::new("output_directory/").join(entry_path);
|
||||
|
||||
// if entry.header().entry_type().is_dir() {
|
||||
// fs::create_dir_all(&full_path)?;
|
||||
// } else {
|
||||
// fs::create_dir_all(&full_path.parent().unwrap())?;
|
||||
|
||||
// let mut file = fs::File::create(&full_path)?;
|
||||
// io::copy(&mut entry, &mut file)?;
|
||||
// }
|
||||
// }
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
pub fn extract_zip(zip_file: &Path) -> io::Result<()> {
|
||||
let file = fs::File::open(zip_file)?;
|
||||
let mut archive = zip::ZipArchive::new(file)?;
|
||||
|
||||
for i in 0..archive.len() {
|
||||
let mut file = archive.by_index(i)?;
|
||||
let outpath = match file.enclosed_name() {
|
||||
Some(path) => path.to_owned(),
|
||||
None => continue,
|
||||
};
|
||||
|
||||
{
|
||||
let comment = file.comment();
|
||||
if !comment.is_empty() {
|
||||
println!("File {} comment: {}", i, comment);
|
||||
}
|
||||
}
|
||||
|
||||
if (*file.name()).ends_with('/') {
|
||||
println!("File {} extracted to \"{}\"", i, outpath.display());
|
||||
fs::create_dir_all(&outpath).unwrap();
|
||||
} else {
|
||||
println!(
|
||||
"File {} extracted to \"{}\" ({} bytes)",
|
||||
i,
|
||||
outpath.display(),
|
||||
file.size()
|
||||
);
|
||||
if let Some(p) = outpath.parent() {
|
||||
if !p.exists() {
|
||||
fs::create_dir_all(p).unwrap();
|
||||
}
|
||||
}
|
||||
let mut outfile = fs::File::create(&outpath).unwrap();
|
||||
io::copy(&mut file, &mut outfile).unwrap();
|
||||
}
|
||||
|
||||
// Get and Set permissions
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
||||
if let Some(mode) = file.unix_mode() {
|
||||
fs::set_permissions(&outpath, fs::Permissions::from_mode(mode)).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn extract_rar(rar_file: &Path) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut archive = Archive::new(rar_file)
|
||||
.open_for_processing()
|
||||
.unwrap();
|
||||
|
||||
while let Some(header) = archive.read_header()? {
|
||||
println!(
|
||||
"{} bytes: {}",
|
||||
header.entry().unpacked_size,
|
||||
header.entry().filename.to_string_lossy(),
|
||||
);
|
||||
archive = if header.entry().is_file() {
|
||||
header.extract()?
|
||||
} else {
|
||||
header.skip()?
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn extract_tar(tar_file: &Path) -> io::Result<()> {
|
||||
let tar_file = fs::File::open(tar_file)?;
|
||||
let mut a = tar::Archive::new(tar_file);
|
||||
|
||||
for i in a.entries()? {
|
||||
let mut i = i?;
|
||||
let entry_path = i.header().path()?;
|
||||
let full_path = Path::new("output_directory/").join(entry_path);
|
||||
|
||||
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 = fs::File::create(&full_path)?;
|
||||
io::copy(&mut i, &mut file)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
146
src/main.rs
146
src/main.rs
|
|
@ -1,72 +1,84 @@
|
|||
use indicatif::{ProgressBar, ProgressStyle};
|
||||
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 = 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 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})")?,
|
||||
);
|
||||
|
||||
files.par_iter().for_each(|file| {
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
mod extractors;
|
||||
use extractors::{extract_zip, extract_rar, extract_tar};
|
||||
fn main() {
|
||||
std::process::exit(run());
|
||||
}
|
||||
|
||||
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));
|
||||
/*
|
||||
TODO: [ ] setup rayon to handle concurrent file processsing when passed
|
||||
more than one file
|
||||
*/
|
||||
/*
|
||||
TODO: [ ] Write for loop to iter over all extensions of a file to handle
|
||||
files that are tared and then compressed ex: foo.tar.gz, foo.tar.gz
|
||||
*/
|
||||
/*
|
||||
TODO: [ ] add support for decompression of:
|
||||
[ ] bz2
|
||||
[ ] tbz2
|
||||
[ ] tgz
|
||||
[ ] txz
|
||||
[ ] lzma
|
||||
[ ] gz
|
||||
[ ] z
|
||||
[ ] 7z
|
||||
[ ] arj
|
||||
[ ] cab
|
||||
[ ] arj
|
||||
[ ] cab
|
||||
[ ] chm
|
||||
[ ] deb
|
||||
[ ] dmg
|
||||
[ ] iso
|
||||
[ ] lzh
|
||||
[ ] msi
|
||||
[ ] rpm
|
||||
[ ] udf
|
||||
[ ] wim
|
||||
[ ] xar
|
||||
[ ] exe
|
||||
*/
|
||||
fn run() -> i32 {
|
||||
let args: Vec<_> = std::env::args().collect();
|
||||
if args.len() < 2 {
|
||||
println!("Usage: {} <filename>", args[0]);
|
||||
return 1;
|
||||
}
|
||||
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);
|
||||
let fname = std::path::Path::new(&*args[1]);
|
||||
if let Some(extension) = fname.extension().and_then(|s| s.to_str()) {
|
||||
match extension {
|
||||
"zip" => {
|
||||
if let Err(err) = extract_zip(&fname) {
|
||||
println!("Error extracting ZIP: {}", err);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
"rar" => {
|
||||
if let Err(err) = extract_rar(&fname) {
|
||||
println!("Error extracting RAR: {}", err);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
"tar" => {
|
||||
if let Err(err) = extract_tar(&fname) {
|
||||
println!("Error extracting TAR: {}", err);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// "xz" => {
|
||||
// if let Err(err) = extract_tar(&fname) {
|
||||
// println!("Error extracting XZ: {}", err);
|
||||
// return 1;
|
||||
// }
|
||||
// }
|
||||
_ => {
|
||||
println!("Unsupported file extension: {}", extension);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Ok(())
|
||||
|
||||
println!("Unknown file format");
|
||||
return 1;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue