浏览代码

ls: Add option to list subdirectories recursively

List subdirectories encountered using -R or --recursive flags with ls.
Ariel Don 4 年之前
父节点
当前提交
4eba921d48
共有 2 个文件被更改,包括 27 次插入5 次删除
  1. 3 0
      Base/usr/share/man/man1/ls.md
  2. 24 5
      Userland/Utilities/ls.cpp

+ 3 - 0
Base/usr/share/man/man1/ls.md

@@ -31,6 +31,7 @@ If no *path* argument is provided the current working directory is used.
 * `-o`, In long format, do not show group information
 * `-h`, `--human-readable`: Print human-readable sizes
 * `-K`, `--no-hyperlinks`: Disable hyperlinks
+* `-R`, `--recursive`: List subdirectories recursively
 
 ## Arguments
 
@@ -43,6 +44,8 @@ If no *path* argument is provided the current working directory is used.
 $ ls
 # List contents of working directory including hidden dot files
 $ ls -la
+# List contents of working directory and its subdirectories
+$ ls -R
 # List contents of /etc/ directory
 $ ls /etc
 # List contents of /etc/ directory including hidden dot files

+ 24 - 5
Userland/Utilities/ls.cpp

@@ -51,6 +51,7 @@ static bool flag_human_readable = false;
 static bool flag_sort_by_timestamp = false;
 static bool flag_reverse_sort = false;
 static bool flag_disable_hyperlinks = false;
+static bool flag_recursive = false;
 
 static size_t terminal_rows = 0;
 static size_t terminal_columns = 0;
@@ -88,7 +89,7 @@ int main(int argc, char** argv)
         return 1;
     }
 
-    Vector<const char*> paths;
+    Vector<String> paths;
 
     Core::ArgsParser args_parser;
     args_parser.set_general_help("List files in a directory.");
@@ -106,6 +107,7 @@ int main(int argc, char** argv)
     args_parser.add_option(flag_hide_group, "In long format, do not show group information", nullptr, 'o');
     args_parser.add_option(flag_human_readable, "Print human-readable sizes", "human-readable", 'h');
     args_parser.add_option(flag_disable_hyperlinks, "Disable hyperlinks", "no-hyperlinks", 'K');
+    args_parser.add_option(flag_recursive, "List subdirectories recursively", "recursive", 'R');
     args_parser.add_positional_argument(paths, "Directory to list", "path", Core::ArgsParser::Required::No);
     args_parser.parse(argc, argv);
 
@@ -129,9 +131,8 @@ int main(int argc, char** argv)
         return do_file_system_object_short(path);
     };
 
-    if (paths.is_empty()) {
+    if (paths.is_empty())
         paths.append(".");
-    }
 
     quick_sort(paths, [](const String& a, const String& b) {
         return a < b;
@@ -142,11 +143,29 @@ int main(int argc, char** argv)
     for (size_t i = 0; i < paths.size(); i++) {
         auto path = paths[i];
 
+        if (flag_recursive && Core::File::is_directory(path)) {
+            size_t subdirs = 0;
+            Core::DirIterator di(path, Core::DirIterator::SkipParentAndBaseDir);
+
+            if (di.has_error()) {
+                status = 1;
+                fprintf(stderr, "%s: %s\n", path.characters(), di.error_string());
+            }
+
+            while (di.has_next()) {
+                String directory = di.next_full_path();
+                if (Core::File::is_directory(directory) && !Core::File::is_link(directory)) {
+                    ++subdirs;
+                    paths.insert(i + subdirs, move(directory));
+                }
+            }
+        }
+
         bool show_dir_separator = paths.size() > 1 && Core::File::is_directory(path) && !flag_list_directories_only;
         if (show_dir_separator) {
-            printf("%s:\n", path);
+            printf("%s:\n", path.characters());
         }
-        auto rc = do_file_system_object(path);
+        auto rc = do_file_system_object(path.characters());
         if (rc != 0)
             status = rc;
         if (show_dir_separator && i != paths.size() - 1) {