From c3d7358df632f8ea3e6a82f3ab74a79a7d17d12b Mon Sep 17 00:00:00 2001 From: Ricardo Iglesias Date: Sun, 25 Apr 2021 12:08:05 -0700 Subject: [PATCH] ls: ignore leading period when sorting by name (#2112) * ls: ignore leading period when sorting by name ls now behaves like GNU ls with respect to sorting files by ignoring leading periods when sorting by main. Added tests to ensure "touch a .a b .b ; ls" returns ".a a .b b" * Replaced clone/collect calls. --- src/uu/ls/src/ls.rs | 8 +++++++- tests/by-util/test_ls.rs | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/uu/ls/src/ls.rs b/src/uu/ls/src/ls.rs index 0351227eb..6317c1975 100644 --- a/src/uu/ls/src/ls.rs +++ b/src/uu/ls/src/ls.rs @@ -1139,7 +1139,13 @@ fn sort_entries(entries: &mut Vec, config: &Config) { entries.sort_by_key(|k| Reverse(k.md().as_ref().map(|md| md.len()).unwrap_or(0))) } // The default sort in GNU ls is case insensitive - Sort::Name => entries.sort_by_cached_key(|k| k.file_name.to_lowercase()), + Sort::Name => entries.sort_by_cached_key(|k| { + let has_dot: bool = k.file_name.starts_with('.'); + let filename_nodot: &str = &k.file_name[if has_dot { 1 } else { 0 }..]; + // We want hidden files to appear before regular files of the same + // name, so we need to negate the "has_dot" variable. + (filename_nodot.to_lowercase(), !has_dot) + }), Sort::Version => entries.sort_by(|k, j| version_cmp::version_cmp(&k.p_buf, &j.p_buf)), Sort::None => {} } diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index 09e02f264..da45934e9 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -481,6 +481,21 @@ fn test_ls_sort_name() { .arg("--sort=name") .succeeds() .stdout_is(["test-1", "test-2", "test-3\n"].join(sep)); + + // Order of a named sort ignores leading dots. + let scene_dot = TestScenario::new(util_name!()); + let at = &scene_dot.fixtures; + at.touch(".a"); + at.touch("a"); + at.touch(".b"); + at.touch("b"); + + scene_dot + .ucmd() + .arg("--sort=name") + .arg("-A") + .succeeds() + .stdout_is([".a", "a", ".b", "b\n"].join(sep)); } #[test]