Skip to content

Commit 87facf6

Browse files
committed
cp: keep handling the rest of the paths if one does not exists
Signed-off-by: Guillaume Ranquet <[email protected]>
1 parent aeafabd commit 87facf6

File tree

2 files changed

+26
-5
lines changed

2 files changed

+26
-5
lines changed

src/uu/cp/src/cp.rs

Lines changed: 25 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,11 @@ 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| {
728+
v.map(|w| PathBuf::from(w))
729+
.collect()
730+
})
727731
.unwrap_or_default();
728732

729733
let (sources, target) = parse_path_args(paths, &options)?;
@@ -1134,7 +1138,24 @@ fn parse_path_args(
11341138
}
11351139
}
11361140

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

11401161
/// 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 & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2693,7 +2693,7 @@ fn test_cp_archive_on_nonexistent_file() {
26932693
.arg(TEST_EXISTING_FILE)
26942694
.fails()
26952695
.stderr_only(
2696-
"cp: cannot stat 'nonexistent_file.txt': No such file or directory (os error 2)\n",
2696+
"cp: cannot stat 'nonexistent_file.txt': No such file or directory\n",
26972697
);
26982698
}
26992699

0 commit comments

Comments
 (0)