summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrendan Coles <bcoles@gmail.com>2020-11-10 17:42:41 +0000
committerAndreas Kling <kling@serenityos.org>2020-11-10 18:56:27 +0100
commit28abfd6290ca8d740ebd8cc2c6893e92bf4c4f0f (patch)
tree9dc30ea20a71569a8672d933a5cf4e8795c05120
parent9b79ea78d3472af70479f4d1cf5fae9d4871bd9d (diff)
downloadserenity-28abfd6290ca8d740ebd8cc2c6893e92bf4c4f0f.zip
Userland: ls: Add `-d` / `--directory` flag
-rw-r--r--Base/usr/share/man/man1/ls.md3
-rw-r--r--Userland/ls.cpp62
2 files changed, 38 insertions, 27 deletions
diff --git a/Base/usr/share/man/man1/ls.md b/Base/usr/share/man/man1/ls.md
index 4bd25515b4..0af1c5bec2 100644
--- a/Base/usr/share/man/man1/ls.md
+++ b/Base/usr/share/man/man1/ls.md
@@ -19,7 +19,8 @@ If no *path* argument is provided the current working directory is used.
* `--help`: Display this message
* `-a`, `--all`: Show dotfiles
* `-A`: Do not list implied . and .. directories
-* `-B`, --ignore-backups`: Do not list implied entries ending with ~
+* `-B`, `--ignore-backups`: Do not list implied entries ending with ~
+* `-d`, `--directory`: List directories themselves, not their contents
* `-l`, `--long`: Display long info
* `-t`: Sort files by timestamp
* `-r`, `--reverse`: Reverse sort order
diff --git a/Userland/ls.cpp b/Userland/ls.cpp
index 017e87d89e..6625563266 100644
--- a/Userland/ls.cpp
+++ b/Userland/ls.cpp
@@ -56,6 +56,7 @@ static bool flag_long = false;
static bool flag_show_dotfiles = false;
static bool flag_show_almost_all_dotfiles = false;
static bool flag_ignore_backups = false;
+static bool flag_list_directories_only = false;
static bool flag_show_inode = false;
static bool flag_print_numeric = false;
static bool flag_hide_group = false;
@@ -102,6 +103,7 @@ int main(int argc, char** argv)
args_parser.add_option(flag_show_dotfiles, "Show dotfiles", "all", 'a');
args_parser.add_option(flag_show_almost_all_dotfiles, "Do not list implied . and .. directories", nullptr, 'A');
args_parser.add_option(flag_ignore_backups, "Do not list implied entries ending with ~", "--ignore-backups", 'B');
+ args_parser.add_option(flag_list_directories_only, "List directories themselves, not their contents", "directory", 'd');
args_parser.add_option(flag_long, "Display long info", "long", 'l');
args_parser.add_option(flag_sort_by_timestamp, "Sort files by timestamp", nullptr, 't');
args_parser.add_option(flag_reverse_sort, "Reverse sort order", "reverse", 'r');
@@ -316,7 +318,26 @@ static bool print_filesystem_object(const String& path, const String& name, cons
static int do_file_system_object_long(const char* path)
{
- Core::DirIterator di(path, !flag_show_dotfiles ? Core::DirIterator::SkipDots : Core::DirIterator::Flags::NoFlags);
+ if (flag_list_directories_only) {
+ struct stat stat;
+ int rc = lstat(path, &stat);
+ if (rc < 0) {
+ perror("lstat");
+ memset(&stat, 0, sizeof(stat));
+ }
+ if (print_filesystem_object(path, path, stat))
+ return 0;
+ return 2;
+ }
+
+ auto flags = Core::DirIterator::SkipDots;
+ if (flag_show_dotfiles)
+ flags = Core::DirIterator::Flags::NoFlags;
+ if (flag_show_almost_all_dotfiles)
+ flags = Core::DirIterator::SkipParentAndBaseDir;
+
+ Core::DirIterator di(path, flags);
+
if (di.has_error()) {
if (di.error() == ENOTDIR) {
struct stat stat;
@@ -345,18 +366,6 @@ static int do_file_system_object_long(const char* path)
metadata.name = di.next_path();
ASSERT(!metadata.name.is_empty());
- if (metadata.name[0] == '.') {
- if (!flag_show_dotfiles)
- continue;
- if (flag_show_almost_all_dotfiles) {
- // skip '.' and '..' directories
- if (metadata.name.length() == 1)
- continue;
- if (metadata.name.length() == 2 && metadata.name[1] == '.')
- continue;
- }
- }
-
if (metadata.name.ends_with('~') && flag_ignore_backups && metadata.name != path)
continue;
@@ -411,7 +420,20 @@ static bool print_filesystem_object_short(const char* path, const char* name, si
int do_file_system_object_short(const char* path)
{
- Core::DirIterator di(path, !flag_show_dotfiles ? Core::DirIterator::SkipDots : Core::DirIterator::Flags::NoFlags);
+ if (flag_list_directories_only) {
+ size_t nprinted = 0;
+ if (print_filesystem_object_short(path, path, &nprinted))
+ return 0;
+ return 2;
+ }
+
+ auto flags = Core::DirIterator::SkipDots;
+ if (flag_show_dotfiles)
+ flags = Core::DirIterator::Flags::NoFlags;
+ if (flag_show_almost_all_dotfiles)
+ flags = Core::DirIterator::SkipParentAndBaseDir;
+
+ Core::DirIterator di(path, flags);
if (di.has_error()) {
if (di.error() == ENOTDIR) {
size_t nprinted = 0;
@@ -430,18 +452,6 @@ int do_file_system_object_short(const char* path)
while (di.has_next()) {
String name = di.next_path();
- if (name[0] == '.') {
- if (!flag_show_dotfiles)
- continue;
- if (flag_show_almost_all_dotfiles) {
- // skip '.' and '..' directories
- if (name.length() == 1)
- continue;
- if (name.length() == 2 && name[1] == '.')
- continue;
- }
- }
-
if (name.ends_with('~') && flag_ignore_backups && name != path)
continue;