diff --git a/src/commands/ls.rs b/src/commands/ls.rs index 18ee5ae745..06c378f397 100644 --- a/src/commands/ls.rs +++ b/src/commands/ls.rs @@ -13,6 +13,8 @@ pub struct LsArgs { pub full: bool, #[serde(rename = "short-names")] pub short_names: bool, + #[serde(rename = "with-symlink-targets")] + pub with_symlink_targets: bool, } impl PerItemCommand for Ls { @@ -29,6 +31,10 @@ impl PerItemCommand for Ls { ) .switch("full", "list all available columns for each entry") .switch("short-names", "only print the file names and not the path") + .switch( + "with-symlink-targets", + "display the paths to the target files that symlinks point to", + ) } fn usage(&self) -> &str { diff --git a/src/data/files.rs b/src/data/files.rs index 89ae02c35d..a0601c8b55 100644 --- a/src/data/files.rs +++ b/src/data/files.rs @@ -7,6 +7,7 @@ pub(crate) fn dir_entry_dict( metadata: &std::fs::Metadata, tag: impl Into, full: bool, + with_symlink_targets: bool, ) -> Result { let mut dict = TaggedDictBuilder::new(tag); dict.insert_untagged("name", UntaggedValue::string(filename.to_string_lossy())); @@ -19,6 +20,22 @@ pub(crate) fn dir_entry_dict( dict.insert_untagged("type", UntaggedValue::string("Symlink")); }; + if full || with_symlink_targets { + if metadata.is_dir() || metadata.is_file() { + dict.insert_untagged("target", UntaggedValue::bytes(0u64)); + } else if let Ok(path_to_link) = filename.read_link() { + dict.insert_untagged( + "target", + UntaggedValue::string(path_to_link.to_string_lossy()), + ); + } else { + dict.insert_untagged( + "target", + UntaggedValue::string("Could not obtain target file's path"), + ); + } + } + if full { dict.insert_untagged( "readonly", diff --git a/src/shell/filesystem_shell.rs b/src/shell/filesystem_shell.rs index 9c7fabb2b5..d0139a4310 100644 --- a/src/shell/filesystem_shell.rs +++ b/src/shell/filesystem_shell.rs @@ -92,6 +92,7 @@ impl Shell for FilesystemShell { path, full, short_names, + with_symlink_targets, }: LsArgs, context: &RunnablePerItemContext, ) -> Result { @@ -166,7 +167,7 @@ impl Shell for FilesystemShell { } } - let value = dir_entry_dict(filename, &metadata, &name_tag, full)?; + let value = dir_entry_dict(filename, &metadata, &name_tag, full, with_symlink_targets)?; yield ReturnSuccess::value(value); } } @@ -217,7 +218,7 @@ impl Shell for FilesystemShell { } } - if let Ok(value) = dir_entry_dict(filename, &metadata, &name_tag, full) { + if let Ok(value) = dir_entry_dict(filename, &metadata, &name_tag, full, with_symlink_targets) { yield ReturnSuccess::value(value); } }