diff --git a/src/uu/du/src/du.rs b/src/uu/du/src/du.rs index 49303a82c..e7b00838e 100644 --- a/src/uu/du/src/du.rs +++ b/src/uu/du/src/du.rs @@ -346,14 +346,21 @@ fn du( } if let Some(inode) = this_stat.inode { - if seen_inodes.contains(&inode) { - if options.count_links { + // Check if the inode has been seen before and if we should skip it + if seen_inodes.contains(&inode) + && (!options.count_links || !options.all) + { + // If `count_links` is enabled and `all` is not, increment the inode count + if options.count_links && !options.all { my_stat.inodes += 1; } + // Skip further processing for this inode continue; } + // Mark this inode as seen seen_inodes.insert(inode); } + if this_stat.is_dir { if options.one_file_system { if let (Some(this_inode), Some(my_inode)) = @@ -550,9 +557,6 @@ impl StatPrinter { } fn convert_size(&self, size: u64) -> String { - if self.inodes { - return size.to_string(); - } match self.size_format { SizeFormat::HumanDecimal => uucore::format::human::human_readable( size, @@ -562,7 +566,14 @@ impl StatPrinter { size, uucore::format::human::SizeFormat::Binary, ), - SizeFormat::BlockSize(block_size) => size.div_ceil(block_size).to_string(), + SizeFormat::BlockSize(block_size) => { + if self.inodes { + // we ignore block size (-B) with --inodes + size.to_string() + } else { + size.div_ceil(block_size).to_string() + } + } } } diff --git a/tests/by-util/test_du.rs b/tests/by-util/test_du.rs index ef6179e02..af9718a4e 100644 --- a/tests/by-util/test_du.rs +++ b/tests/by-util/test_du.rs @@ -546,6 +546,33 @@ fn test_du_inodes_with_count_links() { } } +#[cfg(not(target_os = "android"))] +#[test] +fn test_du_inodes_with_count_links_all() { + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; + + at.mkdir("d"); + at.mkdir("d/d"); + at.touch("d/f"); + at.hard_link("d/f", "d/h"); + + let result = ts.ucmd().arg("--inodes").arg("-al").arg("d").succeeds(); + result.no_stderr(); + + let mut result_seq: Vec = result + .stdout_str() + .split('\n') + .filter(|x| !x.is_empty()) + .map(|x| x.parse().unwrap()) + .collect(); + result_seq.sort_unstable(); + #[cfg(windows)] + assert_eq!(result_seq, ["1\td\\d", "1\td\\f", "1\td\\h", "4\td"]); + #[cfg(not(windows))] + assert_eq!(result_seq, ["1\td/d", "1\td/f", "1\td/h", "4\td"]); +} + #[test] fn test_du_h_flag_empty_file() { new_ucmd!() @@ -1171,3 +1198,25 @@ fn test_invalid_time_style() { .succeeds() .stdout_does_not_contain("du: invalid argument 'banana' for 'time style'"); } + +#[test] +fn test_human_size() { + use std::fs::File; + + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; + let dir = at.plus_as_string("d"); + at.mkdir(&dir); + + for i in 1..=1023 { + let file_path = format!("{dir}/file{i}"); + File::create(&file_path).expect("Failed to create file"); + } + + ts.ucmd() + .arg("--inodes") + .arg("-h") + .arg(&dir) + .succeeds() + .stdout_contains(format!("1.0K {dir}")); +}