Skip to content

Commit 61e0450

Browse files
mvo5cakebaker
authored andcommitted
du: give -h output the same precision as GNU coreutils
When printing the `du -h` output GNU coreutils does autoscale the size, e.g. ``` $ truncate -s12M a $ truncate -s8500 b $ truncate -s133456345 c $ truncate -s56990456345 d $ du -h --apparent-size a b c d 12M a 8,4K b 128M c 54G d ``` Align our version to do the same by sharing the code with `ls`. Closes: #6159
1 parent d07fb73 commit 61e0450

File tree

3 files changed

+41
-19
lines changed

3 files changed

+41
-19
lines changed

src/uu/du/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ chrono = { workspace = true }
1919
# For the --exclude & --exclude-from options
2020
glob = { workspace = true }
2121
clap = { workspace = true }
22-
uucore = { workspace = true }
22+
uucore = { workspace = true, features = ["format"] }
2323

2424
[target.'cfg(target_os = "windows")'.dependencies]
2525
windows-sys = { workspace = true, features = [

src/uu/du/src/du.rs

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,6 @@ const ABOUT: &str = help_about!("du.md");
7575
const AFTER_HELP: &str = help_section!("after help", "du.md");
7676
const USAGE: &str = help_usage!("du.md");
7777

78-
// TODO: Support Z & Y (currently limited by size of u64)
79-
const UNITS: [(char, u32); 6] = [('E', 6), ('P', 5), ('T', 4), ('G', 3), ('M', 2), ('K', 1)];
80-
8178
struct TraversalOptions {
8279
all: bool,
8380
separate_dirs: bool,
@@ -117,7 +114,8 @@ enum Time {
117114

118115
#[derive(Clone)]
119116
enum SizeFormat {
120-
Human(u64),
117+
HumanDecimal,
118+
HumanBinary,
121119
BlockSize(u64),
122120
}
123121

@@ -549,18 +547,14 @@ impl StatPrinter {
549547
return size.to_string();
550548
}
551549
match self.size_format {
552-
SizeFormat::Human(multiplier) => {
553-
if size == 0 {
554-
return "0".to_string();
555-
}
556-
for &(unit, power) in &UNITS {
557-
let limit = multiplier.pow(power);
558-
if size >= limit {
559-
return format!("{:.1}{}", (size as f64) / (limit as f64), unit);
560-
}
561-
}
562-
format!("{size}B")
563-
}
550+
SizeFormat::HumanDecimal => uucore::format::human::human_readable(
551+
size,
552+
uucore::format::human::SizeFormat::Decimal,
553+
),
554+
SizeFormat::HumanBinary => uucore::format::human::human_readable(
555+
size,
556+
uucore::format::human::SizeFormat::Binary,
557+
),
564558
SizeFormat::BlockSize(block_size) => div_ceil(size, block_size).to_string(),
565559
}
566560
}
@@ -688,9 +682,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
688682
});
689683

690684
let size_format = if matches.get_flag(options::HUMAN_READABLE) {
691-
SizeFormat::Human(1024)
685+
SizeFormat::HumanBinary
692686
} else if matches.get_flag(options::SI) {
693-
SizeFormat::Human(1000)
687+
SizeFormat::HumanDecimal
694688
} else if matches.get_flag(options::BYTES) {
695689
SizeFormat::BlockSize(1)
696690
} else if matches.get_flag(options::BLOCK_SIZE_1K) {

tests/by-util/test_du.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,34 @@ fn test_du_h_flag_empty_file() {
543543
.stdout_only("0\tempty.txt\n");
544544
}
545545

546+
#[test]
547+
fn test_du_h_precision() {
548+
let test_cases = [
549+
(133456345, "128M"),
550+
(12 * 1024 * 1024, "12M"),
551+
(8500, "8.4K"),
552+
];
553+
554+
for &(test_len, expected_output) in &test_cases {
555+
let (at, mut ucmd) = at_and_ucmd!();
556+
557+
let fpath = at.plus("test.txt");
558+
std::fs::File::create(&fpath)
559+
.expect("cannot create test file")
560+
.set_len(test_len)
561+
.expect("cannot truncate test len to size");
562+
ucmd.arg("-h")
563+
.arg("--apparent-size")
564+
.arg(&fpath)
565+
.succeeds()
566+
.stdout_only(format!(
567+
"{}\t{}\n",
568+
expected_output,
569+
&fpath.to_string_lossy()
570+
));
571+
}
572+
}
573+
546574
#[cfg(feature = "touch")]
547575
#[test]
548576
fn test_du_time() {

0 commit comments

Comments
 (0)