diff --git a/src/uu/sort/src/sort.rs b/src/uu/sort/src/sort.rs index 8c27910dce8..2a887249ee5 100644 --- a/src/uu/sort/src/sort.rs +++ b/src/uu/sort/src/sort.rs @@ -1846,11 +1846,12 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { uucore::clap_localization::handle_clap_result_with_exit_code(uu_app(), processed_args, 2)?; // Prevent -o/--output to be specified multiple times - if matches - .get_occurrences::(options::OUTPUT) - .is_some_and(|out| out.len() > 1) - { - return Err(SortError::MultipleOutputFiles.into()); + if let Some(mut outputs) = matches.get_many::(options::OUTPUT) { + if let Some(first) = outputs.next() { + if outputs.any(|out| out != first) { + return Err(SortError::MultipleOutputFiles.into()); + } + } } settings.debug = matches.get_flag(options::DEBUG); @@ -2616,17 +2617,17 @@ fn compare_by<'a>( } /// Compare two byte slices in ASCII case-insensitive order without allocating. -/// We lower each byte on the fly so that binary input (including `NUL`) stays +/// We upper each byte on the fly so that binary input (including `NUL`) stays /// untouched and we avoid locale-sensitive routines such as `strcasecmp`. fn ascii_case_insensitive_cmp(a: &[u8], b: &[u8]) -> Ordering { #[inline] - fn lower(byte: u8) -> u8 { - byte.to_ascii_lowercase() + fn fold(byte: u8) -> u8 { + byte.to_ascii_uppercase() } for (lhs, rhs) in a.iter().copied().zip(b.iter().copied()) { - let l = lower(lhs); - let r = lower(rhs); + let l = fold(lhs); + let r = fold(rhs); if l != r { return l.cmp(&r); } diff --git a/tests/by-util/test_sort.rs b/tests/by-util/test_sort.rs index 0106d719fad..0972cae0392 100644 --- a/tests/by-util/test_sort.rs +++ b/tests/by-util/test_sort.rs @@ -208,6 +208,24 @@ fn test_version_sort_stable() { .stdout_is("0.1\n0.02\n0.2\n0.002\n0.3\n"); } +#[test] +fn test_ignore_case_orders_punctuation_after_letters() { + new_ucmd!() + .arg("-f") + .pipe_in("A\na\n_\n") + .succeeds() + .stdout_is("A\na\n_\n"); +} + +#[test] +fn test_ignore_case_unique_orders_punctuation_after_letters() { + new_ucmd!() + .arg("-fu") + .pipe_in("a\n_\n") + .succeeds() + .stdout_is("a\n_\n"); +} + #[test] fn test_human_numeric_whitespace() { test_helper( @@ -1450,6 +1468,16 @@ fn test_multiple_output_files() { .stderr_is("sort: multiple output files specified\n"); } +#[test] +// Test for GNU tests/sort/sort.pl "o3" +fn test_duplicate_output_files_allowed() { + new_ucmd!() + .args(&["-o", "foo", "-o", "foo"]) + .pipe_in("") + .succeeds() + .no_stderr(); +} + #[test] fn test_output_file_with_leading_dash() { let test_cases = [