diff --git a/crates/nu-command/src/filesystem/rm.rs b/crates/nu-command/src/filesystem/rm.rs index a05668a439..17ecb65787 100644 --- a/crates/nu-command/src/filesystem/rm.rs +++ b/crates/nu-command/src/filesystem/rm.rs @@ -381,11 +381,23 @@ fn rm( { unreachable!() } - } else if metadata.is_file() - || is_socket - || is_fifo - || metadata.file_type().is_symlink() - { + } else if metadata.is_symlink() { + // In Windows, symlink pointing to a directory can be removed using + // std::fs::remove_dir instead of std::fs::remove_file. + #[cfg(windows)] + { + f.metadata().and_then(|metadata| { + if metadata.is_dir() { + std::fs::remove_dir(&f) + } else { + std::fs::remove_file(&f) + } + }) + } + + #[cfg(not(windows))] + std::fs::remove_file(&f) + } else if metadata.is_file() || is_socket || is_fifo { std::fs::remove_file(&f) } else { std::fs::remove_dir_all(&f) diff --git a/crates/nu-command/tests/commands/rm.rs b/crates/nu-command/tests/commands/rm.rs index 90e697c313..2b9345e2f8 100644 --- a/crates/nu-command/tests/commands/rm.rs +++ b/crates/nu-command/tests/commands/rm.rs @@ -375,6 +375,19 @@ fn removes_symlink() { }); } +#[test] +fn removes_symlink_pointing_to_directory() { + Playground::setup("rm_symlink_to_directory", |dirs, sandbox| { + sandbox.mkdir("test").symlink("test", "test_link"); + + nu!(cwd: sandbox.cwd(), "rm test_link"); + + assert!(!dirs.test().join("test_link").exists()); + // The pointed directory should not be deleted. + assert!(dirs.test().join("test").exists()); + }); +} + #[test] fn removes_file_after_cd() { Playground::setup("rm_after_cd", |dirs, sandbox| {