mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
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
This commit is contained in:
parent
d07fb73630
commit
61e0450c66
3 changed files with 41 additions and 19 deletions
|
@ -19,7 +19,7 @@ chrono = { workspace = true }
|
||||||
# For the --exclude & --exclude-from options
|
# For the --exclude & --exclude-from options
|
||||||
glob = { workspace = true }
|
glob = { workspace = true }
|
||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
uucore = { workspace = true }
|
uucore = { workspace = true, features = ["format"] }
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
windows-sys = { workspace = true, features = [
|
windows-sys = { workspace = true, features = [
|
||||||
|
|
|
@ -75,9 +75,6 @@ const ABOUT: &str = help_about!("du.md");
|
||||||
const AFTER_HELP: &str = help_section!("after help", "du.md");
|
const AFTER_HELP: &str = help_section!("after help", "du.md");
|
||||||
const USAGE: &str = help_usage!("du.md");
|
const USAGE: &str = help_usage!("du.md");
|
||||||
|
|
||||||
// TODO: Support Z & Y (currently limited by size of u64)
|
|
||||||
const UNITS: [(char, u32); 6] = [('E', 6), ('P', 5), ('T', 4), ('G', 3), ('M', 2), ('K', 1)];
|
|
||||||
|
|
||||||
struct TraversalOptions {
|
struct TraversalOptions {
|
||||||
all: bool,
|
all: bool,
|
||||||
separate_dirs: bool,
|
separate_dirs: bool,
|
||||||
|
@ -117,7 +114,8 @@ enum Time {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
enum SizeFormat {
|
enum SizeFormat {
|
||||||
Human(u64),
|
HumanDecimal,
|
||||||
|
HumanBinary,
|
||||||
BlockSize(u64),
|
BlockSize(u64),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,18 +547,14 @@ impl StatPrinter {
|
||||||
return size.to_string();
|
return size.to_string();
|
||||||
}
|
}
|
||||||
match self.size_format {
|
match self.size_format {
|
||||||
SizeFormat::Human(multiplier) => {
|
SizeFormat::HumanDecimal => uucore::format::human::human_readable(
|
||||||
if size == 0 {
|
size,
|
||||||
return "0".to_string();
|
uucore::format::human::SizeFormat::Decimal,
|
||||||
}
|
),
|
||||||
for &(unit, power) in &UNITS {
|
SizeFormat::HumanBinary => uucore::format::human::human_readable(
|
||||||
let limit = multiplier.pow(power);
|
size,
|
||||||
if size >= limit {
|
uucore::format::human::SizeFormat::Binary,
|
||||||
return format!("{:.1}{}", (size as f64) / (limit as f64), unit);
|
),
|
||||||
}
|
|
||||||
}
|
|
||||||
format!("{size}B")
|
|
||||||
}
|
|
||||||
SizeFormat::BlockSize(block_size) => div_ceil(size, block_size).to_string(),
|
SizeFormat::BlockSize(block_size) => div_ceil(size, block_size).to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -688,9 +682,9 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
});
|
});
|
||||||
|
|
||||||
let size_format = if matches.get_flag(options::HUMAN_READABLE) {
|
let size_format = if matches.get_flag(options::HUMAN_READABLE) {
|
||||||
SizeFormat::Human(1024)
|
SizeFormat::HumanBinary
|
||||||
} else if matches.get_flag(options::SI) {
|
} else if matches.get_flag(options::SI) {
|
||||||
SizeFormat::Human(1000)
|
SizeFormat::HumanDecimal
|
||||||
} else if matches.get_flag(options::BYTES) {
|
} else if matches.get_flag(options::BYTES) {
|
||||||
SizeFormat::BlockSize(1)
|
SizeFormat::BlockSize(1)
|
||||||
} else if matches.get_flag(options::BLOCK_SIZE_1K) {
|
} else if matches.get_flag(options::BLOCK_SIZE_1K) {
|
||||||
|
|
|
@ -543,6 +543,34 @@ fn test_du_h_flag_empty_file() {
|
||||||
.stdout_only("0\tempty.txt\n");
|
.stdout_only("0\tempty.txt\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_du_h_precision() {
|
||||||
|
let test_cases = [
|
||||||
|
(133456345, "128M"),
|
||||||
|
(12 * 1024 * 1024, "12M"),
|
||||||
|
(8500, "8.4K"),
|
||||||
|
];
|
||||||
|
|
||||||
|
for &(test_len, expected_output) in &test_cases {
|
||||||
|
let (at, mut ucmd) = at_and_ucmd!();
|
||||||
|
|
||||||
|
let fpath = at.plus("test.txt");
|
||||||
|
std::fs::File::create(&fpath)
|
||||||
|
.expect("cannot create test file")
|
||||||
|
.set_len(test_len)
|
||||||
|
.expect("cannot truncate test len to size");
|
||||||
|
ucmd.arg("-h")
|
||||||
|
.arg("--apparent-size")
|
||||||
|
.arg(&fpath)
|
||||||
|
.succeeds()
|
||||||
|
.stdout_only(format!(
|
||||||
|
"{}\t{}\n",
|
||||||
|
expected_output,
|
||||||
|
&fpath.to_string_lossy()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "touch")]
|
#[cfg(feature = "touch")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_du_time() {
|
fn test_du_time() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue