diff --git a/crates/nu-command/tests/commands/rm.rs b/crates/nu-command/tests/commands/rm.rs index f43d8fb6..4a20eb38 100644 --- a/crates/nu-command/tests/commands/rm.rs +++ b/crates/nu-command/tests/commands/rm.rs @@ -276,3 +276,33 @@ fn no_errors_if_attempting_to_delete_non_existent_file_with_f_flag() { assert!(!actual.err.contains("no valid path")); }) } + +#[test] +fn rm_wildcard_keeps_dotfiles() { + Playground::setup("rm_test_15", |dirs, sandbox| { + sandbox.with_files(vec![EmptyFile("foo"), EmptyFile(".bar")]); + + nu!( + cwd: dirs.test(), + r#"rm *"# + ); + + assert!(!files_exist_at(vec!["foo"], dirs.test())); + assert!(files_exist_at(vec![".bar"], dirs.test())); + }) +} + +#[test] +fn rm_wildcard_leading_dot_deletes_dotfiles() { + Playground::setup("rm_test_16", |dirs, sandbox| { + sandbox.with_files(vec![EmptyFile("foo"), EmptyFile(".bar")]); + + nu!( + cwd: dirs.test(), + r#"rm .*"# + ); + + assert!(files_exist_at(vec!["foo"], dirs.test())); + assert!(!files_exist_at(vec![".bar"], dirs.test())); + }) +} diff --git a/crates/nu-engine/src/filesystem/filesystem_shell.rs b/crates/nu-engine/src/filesystem/filesystem_shell.rs index 2a531aa3..75cdb027 100644 --- a/crates/nu-engine/src/filesystem/filesystem_shell.rs +++ b/crates/nu-engine/src/filesystem/filesystem_shell.rs @@ -643,11 +643,25 @@ impl Shell for FilesystemShell { } let path = path.join(&target.item); - match glob::glob(&path.to_string_lossy()) { + match glob::glob_with( + &path.to_string_lossy(), + glob::MatchOptions { + require_literal_leading_dot: true, + ..Default::default() + }, + ) { Ok(files) => { for file in files { match file { Ok(ref f) => { + // It is not appropriate to try and remove the + // current directory or its parent when using + // glob patterns. + let name = format!("{}", f.display()); + if name.ends_with("/.") || name.ends_with("/..") { + continue; + } + all_targets .entry(f.clone()) .or_insert_with(|| target.tag.clone());