diff --git a/crates/nu-cli/src/commands/du.rs b/crates/nu-cli/src/commands/du.rs index 3a1e254d31..5dd3f7793e 100644 --- a/crates/nu-cli/src/commands/du.rs +++ b/crates/nu-cli/src/commands/du.rs @@ -143,7 +143,7 @@ fn du(args: DuArgs, ctx: RunnableContext) -> Result { Ok(stream.to_output_stream()) } -struct DirBuilder { +pub struct DirBuilder { tag: Tag, min: Option, deref: bool, @@ -151,7 +151,25 @@ struct DirBuilder { all: bool, } -struct DirInfo { +impl DirBuilder { + pub fn new( + tag: Tag, + min: Option, + deref: bool, + exclude: Option, + all: bool, + ) -> DirBuilder { + DirBuilder { + tag, + min, + deref, + exclude, + all, + } + } +} + +pub struct DirInfo { dirs: Vec, files: Vec, errors: Vec, @@ -194,7 +212,7 @@ impl FileInfo { } impl DirInfo { - fn new(path: impl Into, params: &DirBuilder, depth: Option) -> Self { + pub fn new(path: impl Into, params: &DirBuilder, depth: Option) -> Self { let path = path.into(); let mut s = Self { @@ -274,6 +292,10 @@ impl DirInfo { self.errors.push(e); self } + + pub fn get_size(&self) -> u64 { + self.size + } } fn glob_err_into(e: GlobError) -> ShellError { diff --git a/crates/nu-cli/src/commands/ls.rs b/crates/nu-cli/src/commands/ls.rs index 5095240eaa..7ad6c03d7b 100644 --- a/crates/nu-cli/src/commands/ls.rs +++ b/crates/nu-cli/src/commands/ls.rs @@ -16,6 +16,8 @@ pub struct LsArgs { pub short_names: bool, #[serde(rename = "with-symlink-targets")] pub with_symlink_targets: bool, + #[serde(rename = "du")] + pub du: bool, } impl WholeStreamCommand for Ls { @@ -46,6 +48,11 @@ impl WholeStreamCommand for Ls { "display the paths to the target files that symlinks point to", Some('w'), ) + .switch( + "du", + "display the apparent directory size in place of the directory metadata size", + Some('d'), + ) } fn usage(&self) -> &str { diff --git a/crates/nu-cli/src/data/files.rs b/crates/nu-cli/src/data/files.rs index 28da7254a9..72971c7fd0 100644 --- a/crates/nu-cli/src/data/files.rs +++ b/crates/nu-cli/src/data/files.rs @@ -1,3 +1,4 @@ +use crate::commands::du::{DirBuilder, DirInfo}; use crate::prelude::*; use nu_errors::ShellError; use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value}; @@ -38,6 +39,7 @@ pub(crate) fn dir_entry_dict( full: bool, short_name: bool, with_symlink_targets: bool, + du: bool, ) -> Result { let tag = tag.into(); let mut dict = TaggedDictBuilder::new(&tag); @@ -125,8 +127,27 @@ pub(crate) fn dir_entry_dict( let mut size_untagged_value: UntaggedValue = UntaggedValue::nothing(); if let Some(md) = metadata { - if md.is_file() { - size_untagged_value = UntaggedValue::bytes(md.len() as u64); + if md.is_dir() { + 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, ¶ms, 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() { if let Ok(symlink_md) = filename.symlink_metadata() { size_untagged_value = UntaggedValue::bytes(symlink_md.len() as u64); diff --git a/crates/nu-cli/src/shell/filesystem_shell.rs b/crates/nu-cli/src/shell/filesystem_shell.rs index f980a032b6..cb863705d6 100644 --- a/crates/nu-cli/src/shell/filesystem_shell.rs +++ b/crates/nu-cli/src/shell/filesystem_shell.rs @@ -107,6 +107,7 @@ impl Shell for FilesystemShell { full, short_names, with_symlink_targets, + du, }: LsArgs, context: &RunnableContext, ) -> Result { @@ -170,7 +171,8 @@ impl Shell for FilesystemShell { name_tag.clone(), full, short_names, - with_symlink_targets + with_symlink_targets, + du, ) .map(|entry| ReturnSuccess::Value(entry.into()))?;