1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

cp: Added -t flag, and fixed path bug for source files.

* Added flag -t/--target-directory
* No longer assumes that the source arguments are files in the CWD (in other words, can copy files from directories other than CWD)
This commit is contained in:
Jeremy Neptune 2016-07-15 11:34:49 -04:00
parent 40ae11b29c
commit 5e03b7c75d
No known key found for this signature in database
GPG key ID: C09EDE50FDEF1BB7

View file

@ -34,7 +34,8 @@ pub fn uumain(args: Vec<String>) -> i32 {
let mut opts = Options::new(); let mut opts = Options::new();
opts.optflag("h", "help", "display this help and exit"); opts.optflag("h", "help", "display this help and exit");
opts.optflag("", "version", "output version information and exit"); opts.optflag("v", "version", "output version information and exit");
opts.optopt("t", "target-directory", "copy all SOURCE arguments into DIRECTORY", "DEST");
let matches = match opts.parse(&args[1..]) { let matches = match opts.parse(&args[1..]) {
Ok(m) => m, Ok(m) => m,
@ -70,26 +71,40 @@ fn help(usage: &str) {
let msg = format!("{0} {1}\n\n\ let msg = format!("{0} {1}\n\n\
Usage: {0} SOURCE DEST\n \ Usage: {0} SOURCE DEST\n \
or: {0} SOURCE... DIRECTORY\n \ or: {0} SOURCE... DIRECTORY\n \
or: {0} -t DIRECTORY SOURCE\n\ or: {0} -t DIRECTORY SOURCE...\n\
\n\ \n\
{2}", NAME, VERSION, usage); {2}", NAME, VERSION, usage);
println!("{}", msg); println!("{}", msg);
} }
fn copy(matches: getopts::Matches) { fn copy(matches: getopts::Matches) {
let sources: Vec<String> = if matches.free.is_empty() { let sources: Vec<String> = if matches.free.is_empty() {
show_error!("Missing SOURCE argument. Try --help."); show_error!("Missing SOURCE or DEST argument. Try --help.");
panic!() panic!()
} else { } else if !matches.opt_present("target-directory") {
// All but the last argument:
matches.free[..matches.free.len() - 1].iter().cloned().collect() matches.free[..matches.free.len() - 1].iter().cloned().collect()
} else {
matches.free.iter().cloned().collect()
}; };
let dest = if matches.free.len() < 2 { let dest_str = if matches.opt_present("target-directory") {
matches.opt_str("target-directory").expect("Option -t/--target-directory requires an argument")
} else {
matches.free[matches.free.len() - 1].clone()
};
let dest = if matches.free.len() < 2 && !matches.opt_present("target-directory") {
show_error!("Missing DEST argument. Try --help."); show_error!("Missing DEST argument. Try --help.");
panic!() panic!()
} else { } else {
// Only the last argument: //the argument to the -t/--target-directory= options
Path::new(&matches.free[matches.free.len() - 1]) let path = Path::new(&dest_str);
if !path.is_dir() && matches.opt_present("target-directory") {
show_error!("Argument to -t/--target-directory must be a directory");
panic!()
} else {
path
}
}; };
assert!(sources.len() >= 1); assert!(sources.len() >= 1);
@ -112,8 +127,11 @@ fn copy(matches: getopts::Matches) {
dest.display()); dest.display());
panic!(); panic!();
} }
let mut full_dest = dest.to_path_buf();
if let Err(err) = fs::copy(source, dest) { if dest.is_dir() {
full_dest.push(source.file_name().unwrap()); //the destination path is the destination
} // directory + the file name we're copying
if let Err(err) = fs::copy(source, full_dest) {
show_error!("{}", err); show_error!("{}", err);
panic!(); panic!();
} }
@ -122,7 +140,6 @@ fn copy(matches: getopts::Matches) {
show_error!("TARGET must be a directory"); show_error!("TARGET must be a directory");
panic!(); panic!();
} }
for src in &sources { for src in &sources {
let source = Path::new(&src); let source = Path::new(&src);
@ -133,7 +150,7 @@ fn copy(matches: getopts::Matches) {
let mut full_dest = dest.to_path_buf(); let mut full_dest = dest.to_path_buf();
full_dest.push(source.to_str().unwrap()); full_dest.push(source.file_name().unwrap());
println!("{}", full_dest.display()); println!("{}", full_dest.display());