Adding partial support for formatting time

This commit is contained in:
Derek Chiang 2013-12-11 05:09:45 -05:00
parent a228acbb50
commit c4db2f3329

137
du/du.rs
View file

@ -20,6 +20,7 @@ use std::path::Path;
use extra::arc::Arc; use extra::arc::Arc;
use extra::future::Future; use extra::future::Future;
use extra::getopts::groups; use extra::getopts::groups;
use extra::time::Timespec;
static VERSION: &'static str = "1.0.0"; static VERSION: &'static str = "1.0.0";
@ -81,12 +82,12 @@ fn main() {
groups::optflag("", "apparent-size", "print apparent sizes, rather than disk usage; groups::optflag("", "apparent-size", "print apparent sizes, rather than disk usage;
although the apparent size is usually smaller, it may be larger due to holes although the apparent size is usually smaller, it may be larger due to holes
in ('sparse') files, internal fragmentation, indirect blocks, and the like"), in ('sparse') files, internal fragmentation, indirect blocks, and the like"),
// // In main // In main
// groups::optopt("B", "block-size", "scale sizes by SIZE before printing them. groups::optopt("B", "block-size", "scale sizes by SIZE before printing them.
// E.g., '-BM' prints sizes in units of 1,048,576 bytes. See SIZE format below.", E.g., '-BM' prints sizes in units of 1,048,576 bytes. See SIZE format below.",
// "SIZE"), "SIZE"),
// // In main // In main
// groups::optflag("b", "bytes", "equivalent to '--apparent-size --block-size=1'"), groups::optflag("b", "bytes", "equivalent to '--apparent-size --block-size=1'"),
// In main // In main
groups::optflag("c", "total", "produce a grand total"), groups::optflag("c", "total", "produce a grand total"),
// In task // In task
@ -104,8 +105,8 @@ fn main() {
groups::optflag("", "si", "like -h, but use powers of 1000 not 1024"), groups::optflag("", "si", "like -h, but use powers of 1000 not 1024"),
// In main // In main
groups::optflag("k", "", "like --block-size=1K"), groups::optflag("k", "", "like --block-size=1K"),
// // In task // In task
// groups::optflag("l", "count-links", "count sizes many times if hard linked"), groups::optflag("l", "count-links", "count sizes many times if hard linked"),
// // In main // // In main
groups::optflag("m", "", "like --block-size=1M"), groups::optflag("m", "", "like --block-size=1M"),
// // In task // // In task
@ -114,7 +115,7 @@ fn main() {
// groups::optflag("P", "no-dereference", "don't follow any symbolic links (this is the default)"), // groups::optflag("P", "no-dereference", "don't follow any symbolic links (this is the default)"),
// // In main // // In main
groups::optflag("0", "null", "end each output line with 0 byte rather than newline"), groups::optflag("0", "null", "end each output line with 0 byte rather than newline"),
// In main? // In main
groups::optflag("S", "separate-dirs", "do not include size of subdirectories"), groups::optflag("S", "separate-dirs", "do not include size of subdirectories"),
// In main // In main
groups::optflag("s", "summarize", "display only a total for each argument"), groups::optflag("s", "summarize", "display only a total for each argument"),
@ -124,19 +125,19 @@ fn main() {
// groups::optopt("X", "exclude-from", "exclude files that match any pattern in FILE", "FILE"), // groups::optopt("X", "exclude-from", "exclude files that match any pattern in FILE", "FILE"),
// // In task // // In task
// groups::optopt("", "exclude", "exclude files that match PATTERN", "PATTERN"), // groups::optopt("", "exclude", "exclude files that match PATTERN", "PATTERN"),
// // In main // In main
groups::optopt("d", "max-depth", "print the total for a directory (or file, with --all) groups::optopt("d", "max-depth", "print the total for a directory (or file, with --all)
only if it is N or fewer levels below the command only if it is N or fewer levels below the command
line argument; --max-depth=0 is the same as --summarize", "N"), line argument; --max-depth=0 is the same as --summarize", "N"),
// // In main // In main
// groups::optflag("", "time", "show time of the last modification of any file in the groups::optflag("", "time", "show time of the last modification of any file in the
// directory, or any of its subdirectories"), directory, or any of its subdirectories"),
// // In main // In main
// groups::optopt("", "time", "show time as WORD instead of modification time: groups::optopt("", "time", "show time as WORD instead of modification time:
// atime, access, use, ctime or status", "WORD"), atime, access, use, ctime or status", "WORD"),
// // In main // In main
// groups::optopt("", "time-style", "show times using style STYLE: groups::optopt("", "time-style", "show times using style STYLE:
// full-iso, long-iso, iso, +FORMAT FORMAT is interpreted like 'date'", "STYLE"), full-iso, long-iso, iso, +FORMAT FORMAT is interpreted like 'date'", "STYLE"),
groups::optflag("", "help", "display this help and exit"), groups::optflag("", "help", "display this help and exit"),
groups::optflag("", "version", "output version information and exit"), groups::optflag("", "version", "output version information and exit"),
]; ];
@ -214,12 +215,51 @@ ers of 1000).");
false => 1024, false => 1024,
}; };
let block_size = match matches.opt_str("block-size") {
Some(s) => {
let mut found_number = false;
let mut found_letter = false;
let mut numbers = ~[];
let mut letters = ~[];
for c in s.chars() {
if found_letter && c.is_digit() || !found_number && !c.is_digit() {
println!("du: invalid --block-size argument '{}'", s);
return
} else if c.is_digit() {
found_number = true;
numbers.push(c as u8);
} else if c.is_alphabetic() {
found_letter = true;
letters.push(c);
}
}
let number = std::uint::parse_bytes(numbers, 10).unwrap();
let multiple = match std::str::from_chars(letters).as_slice() {
"K" => 1024, "M" => 1024 * 1024, "G" => 1024 * 1024 * 1024,
"T" => 1024 * 1024 * 1024 * 1024, "P" => 1024 * 1024 * 1024 * 1024 * 1024,
"E" => 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
"Z" => 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
"Y" => 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
"KB" => 1000, "MB" => 1000 * 1000, "GB" => 1000 * 1000 * 1000,
"TB" => 1000 * 1000 * 1000 * 1000, "PB" => 1000 * 1000 * 1000 * 1000 * 1000,
"EB" => 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
"ZB" => 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
"YB" => 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
_ => {
println!("du: invalid --block-size argument '{}'", s); return
}
};
number * multiple
},
None => 1024
};
let convert_size = |size: u64| -> ~str { let convert_size = |size: u64| -> ~str {
if matches.opt_present("human-readable") || matches.opt_present("si") { if matches.opt_present("human-readable") || matches.opt_present("si") {
if size > MB { if size > MB {
format!("{:.1f}MB", (size as f64) / (MB as f64)) format!("{:.1f}M", (size as f64) / (MB as f64))
} else if size > KB { } else if size > KB {
format!("{:.1f}KB", (size as f64) / (KB as f64)) format!("{:.1f}K", (size as f64) / (KB as f64))
} else { } else {
format!("{}B", size) format!("{}B", size)
} }
@ -228,10 +268,31 @@ ers of 1000).");
} else if matches.opt_present("m") { } else if matches.opt_present("m") {
format!("{}", ((size as f64) / (MB as f64)).ceil()) format!("{}", ((size as f64) / (MB as f64)).ceil())
} else { } else {
format!("{}", ((size as f64) / (KB as f64)).ceil()) format!("{}", ((size as f64) / (block_size as f64)).ceil())
} }
}; };
let time_format_str = match matches.opt_str("time-style") {
Some(s) => {
match s.as_slice() {
"full-iso" => "%Y-%m-%d %H:%M:%S.%N %z",
"long-iso" => "%Y-%m-%d %H:%M",
"iso" => "%Y-%m-%d",
_ => {
println("
du: invalid argument 'awdwa' for 'time style'
Valid arguments are:
- 'full-iso'
- 'long-iso'
- 'iso'
Try 'du --help' for more information.");
return
}
}
},
None => "%Y-%m-%d %H:%M"
};
let line_separator = match matches.opt_present("0") { let line_separator = match matches.opt_present("0") {
true => "\0", true => "\0",
false => "\n", false => "\n",
@ -239,19 +300,45 @@ ers of 1000).");
let mut grand_total = 0; let mut grand_total = 0;
for path_str in strs.iter() { for path_str in strs.iter() {
let path = Path::init(path_str.clone()); let path = Path::new(path_str.clone());
let iter = du(&path, options_arc.clone(), 0).move_iter(); let iter = du(&path, options_arc.clone(), 0).move_iter();
let (_, len) = iter.size_hint(); let (_, len) = iter.size_hint();
let len = len.unwrap(); let len = len.unwrap();
for (index, stat_arc) in iter.enumerate() { for (index, stat_arc) in iter.enumerate() {
let stat = stat_arc.get(); let stat = stat_arc.get();
let size = match matches.opt_present("apparent-size") { let size = match matches.opt_present("apparent-size") {
true => stat.size, true => stat.unstable.nlink * stat.size,
// C's stat is such that each block is assume to be 512 bytes // C's stat is such that each block is assume to be 512 bytes
// See: http://linux.die.net/man/2/stat // See: http://linux.die.net/man/2/stat
false => stat.unstable.blocks * 512, false => stat.unstable.blocks * 512,
}; };
print!("{:<10} {}", convert_size(size), stat.path.display()); if matches.opt_present("time") {
let time_str = {
let (secs, nsecs) = {
let time = match matches.opt_str("time") {
Some(s) => match s.as_slice() {
"accessed" => stat.accessed,
"created" => stat.created,
"modified" => stat.modified,
_ => {
println("du: invalid argument 'modified' for '--time'
Valid arguments are:
- 'accessed', 'created', 'modified'
Try 'du --help' for more information.");
return
}
},
None => stat.modified
};
((time / 1000) as i64, (time % 1000 * 1000) as i32)
};
let time_spec = Timespec::new(secs, nsecs);
extra::time::at(time_spec).strftime(time_format_str)
};
print!("{:<10} {:<30} {}", convert_size(size), time_str, stat.path.display());
} else {
print!("{:<10} {}", convert_size(size), stat.path.display());
}
print(line_separator); print(line_separator);
if options.total && index == (len - 1) { if options.total && index == (len - 1) {
// The last element will be the total size of the the path under // The last element will be the total size of the the path under