diff --git a/src/uu/cp/src/cp.rs b/src/uu/cp/src/cp.rs index 3a1697039..b3ef4f56a 100644 --- a/src/uu/cp/src/cp.rs +++ b/src/uu/cp/src/cp.rs @@ -1264,6 +1264,12 @@ fn copy_file( symlinked_files: &mut HashSet, source_in_command_line: bool, ) -> CopyResult<()> { + if options.update && options.overwrite == OverwriteMode::Interactive(ClobberMode::Standard) { + // `cp -i --update old new` when `new` exists doesn't copy anything + // and exit with 0 + return Ok(()); + } + if file_or_link_exists(dest) { handle_existing_dest(source, dest, options, source_in_command_line)?; } diff --git a/src/uu/mv/src/mv.rs b/src/uu/mv/src/mv.rs index ded46539f..4697fac4a 100644 --- a/src/uu/mv/src/mv.rs +++ b/src/uu/mv/src/mv.rs @@ -371,6 +371,12 @@ fn rename(from: &Path, to: &Path, b: &Behavior) -> io::Result<()> { let mut backup_path = None; if to.exists() { + if b.update && b.overwrite == OverwriteMode::Interactive { + // `mv -i --update old new` when `new` exists doesn't move anything + // and exit with 0 + return Ok(()); + } + match b.overwrite { OverwriteMode::NoClobber => return Ok(()), OverwriteMode::Interactive => { diff --git a/tests/by-util/test_cp.rs b/tests/by-util/test_cp.rs index 8285905c5..5a97db0bd 100644 --- a/tests/by-util/test_cp.rs +++ b/tests/by-util/test_cp.rs @@ -215,6 +215,18 @@ fn test_cp_target_directory_is_file() { .stderr_contains(format!("'{}' is not a directory", TEST_HOW_ARE_YOU_SOURCE)); } +#[test] +fn test_cp_arg_update_interactive() { + new_ucmd!() + .arg(TEST_HELLO_WORLD_SOURCE) + .arg(TEST_HOW_ARE_YOU_SOURCE) + .arg("-i") + .arg("--update") + .succeeds() + .no_stdout() + .no_stderr(); +} + #[test] fn test_cp_arg_interactive() { let (at, mut ucmd) = at_and_ucmd!(); diff --git a/tests/by-util/test_mv.rs b/tests/by-util/test_mv.rs index 200053ba6..9dd06c9f1 100644 --- a/tests/by-util/test_mv.rs +++ b/tests/by-util/test_mv.rs @@ -184,6 +184,25 @@ fn test_mv_interactive() { assert!(at.file_exists(file_b)); } +#[test] +fn test_mv_arg_update_interactive() { + let (at, mut ucmd) = at_and_ucmd!(); + + let file_a = "test_mv_replace_file_a"; + let file_b = "test_mv_replace_file_b"; + + at.touch(file_a); + at.touch(file_b); + + ucmd.arg(file_a) + .arg(file_b) + .arg("-i") + .arg("--update") + .succeeds() + .no_stdout() + .no_stderr(); +} + #[test] fn test_mv_no_clobber() { let (at, mut ucmd) = at_and_ucmd!();