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())
}
struct DirBuilder {
pub struct DirBuilder {
tag: Tag,
min: Option<u64>,
deref: bool,
@ -151,7 +151,25 @@ struct DirBuilder {
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>,
files: Vec<FileInfo>,
errors: Vec<ShellError>,
@ -194,7 +212,7 @@ impl FileInfo {
}
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 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 {

View File

@ -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 {

View File

@ -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<Value, ShellError> {
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, &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() {
if let Ok(symlink_md) = filename.symlink_metadata() {
size_untagged_value = UntaggedValue::bytes(symlink_md.len() as u64);

View File

@ -107,6 +107,7 @@ impl Shell for FilesystemShell {
full,
short_names,
with_symlink_targets,
du,
}: LsArgs,
context: &RunnableContext,
) -> Result<OutputStream, ShellError> {
@ -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()))?;