diff --git a/crates/nu-cli/src/shell/filesystem_shell.rs b/crates/nu-cli/src/shell/filesystem_shell.rs index 9c39f13e36..1554c5f7a5 100644 --- a/crates/nu-cli/src/shell/filesystem_shell.rs +++ b/crates/nu-cli/src/shell/filesystem_shell.rs @@ -631,11 +631,27 @@ impl Shell for FilesystemShell { match destination.file_name() { Some(name) => PathBuf::from(name), None => { - return Err(ShellError::labeled_error( - "Rename aborted. Not a valid destination", - "not a valid destination", - dst.tag, - )) + let name_maybe = + destination.components().next_back().and_then( + |component| match component { + Component::RootDir => Some(PathBuf::from("/")), + Component::ParentDir => destination + .parent() + .and_then(|parent| parent.file_name()) + .map(PathBuf::from), + _ => None, + }, + ); + + if let Some(name) = name_maybe { + name + } else { + return Err(ShellError::labeled_error( + "Rename aborted. Not a valid destination", + "not a valid destination", + dst.tag, + )); + } } } }; diff --git a/crates/nu-cli/tests/commands/mv.rs b/crates/nu-cli/tests/commands/mv.rs index d4fa014809..c49c27bec7 100644 --- a/crates/nu-cli/tests/commands/mv.rs +++ b/crates/nu-cli/tests/commands/mv.rs @@ -230,3 +230,23 @@ fn errors_if_source_doesnt_exist() { assert!(actual.contains("Invalid File or Pattern")); }) } + +#[test] +fn does_not_error_on_relative_parent_path() { + Playground::setup("mv_test_11", |dirs, sandbox| { + sandbox + .mkdir("first") + .with_files(vec![EmptyFile("first/william_hartnell.txt")]); + + let original = dirs.test().join("first/william_hartnell.txt"); + let expected = dirs.test().join("william_hartnell.txt"); + + nu!( + cwd: dirs.test().join("first"), + "mv william_hartnell.txt ./.." + ); + + assert!(!original.exists()); + assert!(expected.exists()); + }) +}