diff --git a/src/uu/cp/src/cp.rs b/src/uu/cp/src/cp.rs index f9f6d8763..da9918365 100644 --- a/src/uu/cp/src/cp.rs +++ b/src/uu/cp/src/cp.rs @@ -1647,6 +1647,14 @@ fn copy_file( dest.display() ))); } + if paths_refer_to_same_file(source, dest, true) + && matches!( + options.overwrite, + OverwriteMode::Clobber(ClobberMode::RemoveDestination) + ) + { + fs::remove_file(dest)?; + } } if file_or_link_exists(dest) { diff --git a/tests/by-util/test_cp.rs b/tests/by-util/test_cp.rs index 9894087e8..b3cc3e0c1 100644 --- a/tests/by-util/test_cp.rs +++ b/tests/by-util/test_cp.rs @@ -2827,6 +2827,22 @@ fn test_cp_mode_hardlink_no_dereference() { assert_eq!(at.read_symlink("z"), "slink"); } +#[test] +fn test_remove_destination_with_destination_being_a_symlink_to_source() { + let (at, mut ucmd) = at_and_ucmd!(); + let file = "file"; + let symlink = "symlink"; + + at.touch(file); + at.symlink_file(file, symlink); + + ucmd.args(&["--remove-destination", file, symlink]) + .succeeds(); + assert!(!at.symlink_exists(symlink)); + assert!(at.file_exists(file)); + assert!(at.file_exists(symlink)); +} + #[test] fn test_remove_destination_symbolic_link_loop() { let (at, mut ucmd) = at_and_ucmd!();