Display either dir metadata size or dir apparent size in ls (#1696)

* Show dir size in ls command

* Add the option to show the apparent directory size via `ls --du`
This commit is contained in:
Joseph T. Lyons 2020-05-03 01:09:17 -04:00 committed by GitHub
parent 0779a46179
commit 8d69c77989
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 6 deletions

View file

@ -143,7 +143,7 @@ fn du(args: DuArgs, ctx: RunnableContext) -> Result<OutputStream, ShellError> {
Ok(stream.to_output_stream()) Ok(stream.to_output_stream())
} }
struct DirBuilder { pub struct DirBuilder {
tag: Tag, tag: Tag,
min: Option<u64>, min: Option<u64>,
deref: bool, deref: bool,
@ -151,7 +151,25 @@ struct DirBuilder {
all: bool, all: bool,
} }
struct DirInfo { impl DirBuilder {
pub fn new(
tag: Tag,
min: Option<u64>,
deref: bool,
exclude: Option<Pattern>,
all: bool,
) -> DirBuilder {
DirBuilder {
tag,
min,
deref,
exclude,
all,
}
}
}
pub struct DirInfo {
dirs: Vec<DirInfo>, dirs: Vec<DirInfo>,
files: Vec<FileInfo>, files: Vec<FileInfo>,
errors: Vec<ShellError>, errors: Vec<ShellError>,
@ -194,7 +212,7 @@ impl FileInfo {
} }
impl DirInfo { impl DirInfo {
fn new(path: impl Into<PathBuf>, params: &DirBuilder, depth: Option<u64>) -> Self { pub fn new(path: impl Into<PathBuf>, params: &DirBuilder, depth: Option<u64>) -> Self {
let path = path.into(); let path = path.into();
let mut s = Self { let mut s = Self {
@ -274,6 +292,10 @@ impl DirInfo {
self.errors.push(e); self.errors.push(e);
self self
} }
pub fn get_size(&self) -> u64 {
self.size
}
} }
fn glob_err_into(e: GlobError) -> ShellError { fn glob_err_into(e: GlobError) -> ShellError {

View file

@ -16,6 +16,8 @@ pub struct LsArgs {
pub short_names: bool, pub short_names: bool,
#[serde(rename = "with-symlink-targets")] #[serde(rename = "with-symlink-targets")]
pub with_symlink_targets: bool, pub with_symlink_targets: bool,
#[serde(rename = "du")]
pub du: bool,
} }
impl WholeStreamCommand for Ls { impl WholeStreamCommand for Ls {
@ -46,6 +48,11 @@ impl WholeStreamCommand for Ls {
"display the paths to the target files that symlinks point to", "display the paths to the target files that symlinks point to",
Some('w'), Some('w'),
) )
.switch(
"du",
"display the apparent directory size in place of the directory metadata size",
Some('d'),
)
} }
fn usage(&self) -> &str { fn usage(&self) -> &str {

View file

@ -1,3 +1,4 @@
use crate::commands::du::{DirBuilder, DirInfo};
use crate::prelude::*; use crate::prelude::*;
use nu_errors::ShellError; use nu_errors::ShellError;
use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value}; use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value};
@ -38,6 +39,7 @@ pub(crate) fn dir_entry_dict(
full: bool, full: bool,
short_name: bool, short_name: bool,
with_symlink_targets: bool, with_symlink_targets: bool,
du: bool,
) -> Result<Value, ShellError> { ) -> Result<Value, ShellError> {
let tag = tag.into(); let tag = tag.into();
let mut dict = TaggedDictBuilder::new(&tag); let mut dict = TaggedDictBuilder::new(&tag);
@ -125,8 +127,27 @@ pub(crate) fn dir_entry_dict(
let mut size_untagged_value: UntaggedValue = UntaggedValue::nothing(); let mut size_untagged_value: UntaggedValue = UntaggedValue::nothing();
if let Some(md) = metadata { if let Some(md) = metadata {
if md.is_file() { if md.is_dir() {
size_untagged_value = UntaggedValue::bytes(md.len() as u64); let dir_size: u64 = if du {
let params = DirBuilder::new(
Tag {
anchor: None,
span: Span::new(0, 2),
},
None,
false,
None,
false,
);
DirInfo::new(filename, &params, None).get_size()
} else {
md.len()
};
size_untagged_value = UntaggedValue::bytes(dir_size);
} else if md.is_file() {
size_untagged_value = UntaggedValue::bytes(md.len());
} else if md.file_type().is_symlink() { } else if md.file_type().is_symlink() {
if let Ok(symlink_md) = filename.symlink_metadata() { if let Ok(symlink_md) = filename.symlink_metadata() {
size_untagged_value = UntaggedValue::bytes(symlink_md.len() as u64); size_untagged_value = UntaggedValue::bytes(symlink_md.len() as u64);

View file

@ -107,6 +107,7 @@ impl Shell for FilesystemShell {
full, full,
short_names, short_names,
with_symlink_targets, with_symlink_targets,
du,
}: LsArgs, }: LsArgs,
context: &RunnableContext, context: &RunnableContext,
) -> Result<OutputStream, ShellError> { ) -> Result<OutputStream, ShellError> {
@ -170,7 +171,8 @@ impl Shell for FilesystemShell {
name_tag.clone(), name_tag.clone(),
full, full,
short_names, short_names,
with_symlink_targets with_symlink_targets,
du,
) )
.map(|entry| ReturnSuccess::Value(entry.into()))?; .map(|entry| ReturnSuccess::Value(entry.into()))?;