diff --git a/src/uu/mv/src/mv.rs b/src/uu/mv/src/mv.rs index 9d8452b1e..20a22043c 100644 --- a/src/uu/mv/src/mv.rs +++ b/src/uu/mv/src/mv.rs @@ -314,6 +314,7 @@ fn handle_two_paths(source: &Path, target: &Path, opts: &Options) -> UResult<()> ) .into()); } + if source.symlink_metadata().is_err() { return Err(if path_ends_with_terminator(source) { MvError::CannotStatNotADirectory(source.quote().to_string()).into() @@ -336,6 +337,13 @@ fn handle_two_paths(source: &Path, target: &Path, opts: &Options) -> UResult<()> } } + if source.parent() == Some(target) { + return Err( + // use source twice to match GNU's error message + MvError::SameFile(source.quote().to_string(), source.quote().to_string()).into(), + ); + } + let target_is_dir = target.is_dir(); let source_is_dir = source.is_dir(); diff --git a/tests/by-util/test_mv.rs b/tests/by-util/test_mv.rs index 6ab989ee4..562e24754 100644 --- a/tests/by-util/test_mv.rs +++ b/tests/by-util/test_mv.rs @@ -402,7 +402,23 @@ fn test_mv_same_file() { ucmd.arg(file_a) .arg(file_a) .fails() - .stderr_is(format!("mv: '{file_a}' and '{file_a}' are the same file\n",)); + .stderr_is(format!("mv: '{file_a}' and '{file_a}' are the same file\n")); +} + +#[test] +fn test_mv_file_to_same_dir() { + let (at, mut ucmd) = at_and_ucmd!(); + let file = "a"; + let dir = "dir"; + let path = &format!("{dir}/{file}"); + + at.mkdir(dir); + at.touch(path); + + ucmd.arg(path) + .arg(dir) + .fails() + .stderr_is(format!("mv: '{path}' and '{path}' are the same file\n")); } #[test]