Skip to content

Commit 5d85b34

Browse files
committed
cp: keep handling the rest of the paths if one does not exists
Signed-off-by: Guillaume Ranquet <granquet@baylibre.com>
1 parent aeafabd commit 5d85b34

File tree

2 files changed

+23
-7
lines changed

2 files changed

+23
-7
lines changed

src/uu/cp/src/cp.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::collections::{HashMap, HashSet};
1010
use std::env;
1111
#[cfg(not(windows))]
1212
use std::ffi::CString;
13+
use std::ffi::OsString;
1314
use std::fs::{self, File, Metadata, OpenOptions, Permissions};
1415
use std::io;
1516
#[cfg(unix)]
@@ -692,7 +693,7 @@ pub fn uu_app() -> Command {
692693
Arg::new(options::PATHS)
693694
.action(ArgAction::Append)
694695
.value_hint(clap::ValueHint::AnyPath)
695-
.value_parser(ValueParser::path_buf()),
696+
.value_parser(clap::value_parser!(OsString)),
696697
)
697698
}
698699

@@ -722,8 +723,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
722723
}
723724

724725
let paths: Vec<PathBuf> = matches
725-
.remove_many::<PathBuf>(options::PATHS)
726-
.map(|v| v.collect())
726+
.remove_many::<OsString>(options::PATHS)
727+
.map(|v| v.map(PathBuf::from).collect())
727728
.unwrap_or_default();
728729

729730
let (sources, target) = parse_path_args(paths, &options)?;
@@ -1134,7 +1135,24 @@ fn parse_path_args(
11341135
}
11351136
}
11361137

1137-
Ok((paths, target))
1138+
// If the path exists and is valid keep it in the argument list.
1139+
// Exception for symlinks as they are a bit more tricky to handle
1140+
// and there's logic further down the execution to handle them.
1141+
let (ok_paths, invalid_paths): (Vec<_>, Vec<_>) = paths
1142+
.into_iter()
1143+
.partition(|p| p.is_symlink() || p.exists());
1144+
1145+
if !invalid_paths.is_empty() {
1146+
for p in invalid_paths.into_iter() {
1147+
eprintln!(
1148+
"cp: cannot stat '{}': No such file or directory",
1149+
p.display()
1150+
);
1151+
}
1152+
set_exit_code(EXIT_ERR);
1153+
}
1154+
1155+
Ok((ok_paths, target))
11381156
}
11391157

11401158
/// When handling errors, we don't always want to show them to the user. This function handles that.

tests/by-util/test_cp.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2692,9 +2692,7 @@ fn test_cp_archive_on_nonexistent_file() {
26922692
.arg(TEST_NONEXISTENT_FILE)
26932693
.arg(TEST_EXISTING_FILE)
26942694
.fails()
2695-
.stderr_only(
2696-
"cp: cannot stat 'nonexistent_file.txt': No such file or directory (os error 2)\n",
2697-
);
2695+
.stderr_only("cp: cannot stat 'nonexistent_file.txt': No such file or directory\n");
26982696
}
26992697

27002698
#[test]

0 commit comments

Comments
 (0)