bug#79710: [PATCH] ls: add --count and --count-list options to display file, directory, and symlink counts and counts with list of contents

Debkanta Mondal <[email protected]>
Newsgroups gmane.comp.gnu.core-utils.bugs
Message-ID <CAJPp_T=ekw7k02vEYuRk3CNCXHfcSa0OJVR0fxFhgFMTrv0FHw@mail.gmail.com>
Hello Coreutils maintainers,

I have attached cleaned logic specific patch file for --count and
--count-list and also
 NEWS patch file for detailed explanation from my side to propose
these changes still after having "ls | wc" with this mail.

Output: If current directory have 5 files, 2 directories and 0 link: then
ls --count
Directories: 2 | Files: 5 | Links: 0
ls --count-list
Directories: 2 | Files: 5 | Links: 0
----------------------------------------------------------------------------------------
CONTAINING ELEMENTS ARE
----------------------------------------------------------------------------------------
Name                           Type   Permissions   Size
Modified
----------------------------------------------------------------------------------------
ABOUT-NLS                 FILE   -rw-r--r--        93787    2023-03-13 23:42
AUTHORS                    FILE   -rw-r--r--        3827
2023-03-13 23:38
COPYING                     FILE   -rw-r--r--        35149
2023-03-13 23:38
ChangeLog                   FILE   -rw-r--r--        324062
2023-04-18 20:02
GNUmakefile                FILE   -rw-r--r--         4589
2023-04-18 19:39
build                              DIR    drwxr-xr-x      160
2025-10-28 23:56
build-aux                       DIR    drwxr-xr-x       800
2023-04-18 20:02


Why do we need a --count option when we have 'ls | wc'"?
    ls --count will count the number of directories, files and symlinks
of current directory user present. and --count-list will print the
count and also print containing items details - like name, size,
permissions, modified datetime, and its type. With --count, you get
everything in one place: directories, files, links, and the table,
without needing to chain commands like ls | wc. It’s simpler, more reliable,
and avoids issues with pipes or parsing output. And --count-list can
give a detailed table of contained elements with type wise count and
all within the ls , just using options flag , no need extra pipeline/
complex command for this simple and frequently required output

The patch was tested on coreutils-9.3 using `make check`, and all tests passed.

Thank you for maintaining Coreutils and for reviewing my contribution!

Signed-off-by: Debkanta Mondal ([email protected])


On Tue, Oct 28, 2025 at 11:27 PM Collin Funk <[email protected]> wrote:
>
> Pádraig Brady <[email protected]> writes:
>
> > On 28/10/2025 15:45, Debkanta Mondal wrote:
> >>   my-count-and-count-list-ls-update.patch
> >> Hello Coreutils maintainers,
> >> This patch adds two new options to `ls`:
> >>    --count       : Display the total number of directories, files and
> >> symbolic links.
> >>    --count-list  : Display a detailed count + list of directories,
> >> files and symbolic links present in the current directory.
> >> The purpose of this update is to make it easier for users to quickly
> >> see
> >> object counts when listing directory contents.
> >> The patch was tested on coreutils-9.3 using `make check`, and all
> >> tests passed.
> >> I have attached the patch file with this email.
> >> Thank you for maintaining Coreutils and for reviewing my
> >> contribution!
> >> Signed-off-by: Debkanta Mondal ([email protected])
> >
> > It's hard to review this patch as it's mostly reindented changes.
> > Can you resend with just the logic changes.
>
> Likewise. The HACKING file has good formatting settings for vim.
>
> The Emacs settings could be improved to add '(c-set-style "GNU")', among
> other things.
>
> Other editors I have tried are bad at GNU formatting.
>
> > Can you give example outputs from the new options.
> > Note new options to ls have a high bar.
>
> My feeling is that the feature is not really needed with GNU find:
>
>     $ find . -maxdepth 1 -type d | wc -l
>     39
>     $ find . -maxdepth 1 -type f | wc -l
>     35
>     $ find . -maxdepth 1 -type l | wc -l
>     2
>
> Collin
ls-count-cleaned.patch (application/octet-stream, 6.4 KB)
--- /Users/debkantamondal/coreutils-original/src/ls.c	2023-03-13 23:38:10
+++ /Users/debkantamondal/coreutils-9.3/src/ls.c	2025-10-28 23:45:27
@@ -282,6 +282,8 @@
 static void indent (size_t from, size_t to);
 static size_t calculate_columns (bool by_columns);
 static void print_current_files (void);
+static void count_elements_in_container();
+static void containers_list();
 static void print_dir (char const *name, char const *realname,
                        bool command_line_arg);
 static size_t print_file_name_and_frills (const struct fileinfo *f,
@@ -522,6 +524,10 @@
 /* Human-readable options for output, when printing block counts.  */
 static int human_output_opts;
 
+/* --count and --coun-list options control */
+static bool count_mode = false;
+static bool count_mode_with_list = false;
+
 /* The units to use when printing block counts.  */
 static uintmax_t output_block_size;
 
@@ -829,6 +835,8 @@
 enum
 {
   AUTHOR_OPTION = CHAR_MAX + 1,
+  COUNT_OPTION,
+  COUNT_OPTION_WITH_LIST,
   BLOCK_SIZE_OPTION,
   COLOR_OPTION,
   DEREFERENCE_COMMAND_LINE_SYMLINK_TO_DIR_OPTION,
@@ -894,6 +902,8 @@
   {"block-size", required_argument, NULL, BLOCK_SIZE_OPTION},
   {"context", no_argument, 0, 'Z'},
   {"author", no_argument, NULL, AUTHOR_OPTION},
+  {"count", no_argument, NULL, COUNT_OPTION},
+  {"count-list", no_argument, NULL, COUNT_OPTION_WITH_LIST},
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
   {NULL, 0, NULL, 0}
@@ -1543,9 +1553,111 @@
 
       /* If execution reaches here, then the program has been
          continued (after being suspended).  */
+    }
+}
+
+static void count_elements_in_container()
+{
+  size_t file_count = 0, dir_count = 0, link_count = 0;
+
+    for (size_t i = 0; i < cwd_n_used; i++)
+    {
+      struct fileinfo *f = sorted_file[i];
+
+      // Ensure we have stat info
+      if (!f->stat_ok)
+      {
+        if (lstat(f->name, &f->stat) == 0)
+          f->stat_ok = true;
+      }
+
+      if (!f->stat_ok)
+        continue;
+
+      
+
+      mode_t mode = f->stat.st_mode;
+
+      if (S_ISDIR(mode))
+        dir_count++;
+      else if (S_ISLNK(mode))
+        link_count++;
+      else if (S_ISREG(mode))
+        file_count++;
     }
+
+    printf("Directories: %zu | Files: %zu | Links: %zu",
+           dir_count, file_count, link_count);
+    if (count_mode_with_list)
+      printf("\n-------------------------------------------------------------------------------\n");
+    else
+      printf("\n");
 }
 
+static void containers_list()
+{
+  // for (size_t i = 0; i < cwd_n_used; i++)
+      printf("CONTAINING ELEMENTS ARE\n-------------------------------------------------------------------------------\n");
+      // print_current_files();
+      printf("%-30s %-6s %-12s %-10s %-20s\n",
+            "Name", "Type", "Permissions", "Size", "Modified");
+      printf("-------------------------------------------------------------------------------\n");
+
+      for (size_t i = 0; i < cwd_n_used; i++)
+      {
+        struct fileinfo *f = sorted_file[i];
+
+        // Ensure stat info
+        if (!f->stat_ok)
+        {
+          if (lstat(f->name, &f->stat) == 0)
+            f->stat_ok = true;
+        }
+
+        if (!f->stat_ok)
+          continue;
+
+        // File type
+        const char *type = "?";
+        if (S_ISDIR(f->stat.st_mode))
+          type = "DIR";
+        else if (S_ISREG(f->stat.st_mode))
+          type = "FILE";
+        else if (S_ISLNK(f->stat.st_mode))
+          type = "LINK";
+
+        // Permissions string
+        char perms[11];
+        mode_t m = f->stat.st_mode;
+        perms[0] = S_ISDIR(m) ? 'd' : (S_ISLNK(m) ? 'l' : '-');
+        perms[1] = (m & S_IRUSR) ? 'r' : '-';
+        perms[2] = (m & S_IWUSR) ? 'w' : '-';
+        perms[3] = (m & S_IXUSR) ? 'x' : '-';
+        perms[4] = (m & S_IRGRP) ? 'r' : '-';
+        perms[5] = (m & S_IWGRP) ? 'w' : '-';
+        perms[6] = (m & S_IXGRP) ? 'x' : '-';
+        perms[7] = (m & S_IROTH) ? 'r' : '-';
+        perms[8] = (m & S_IWOTH) ? 'w' : '-';
+        perms[9] = (m & S_IXOTH) ? 'x' : '-';
+        perms[10] = '\0';
+
+        // Size
+        long size = (long)f->stat.st_size;
+
+        // Modified time
+        char mod_time[20];
+        struct tm *tm_info = localtime(&f->stat.st_mtime);
+        strftime(mod_time, sizeof(mod_time), "%Y-%m-%d %H:%M", tm_info);
+
+        // Print row (with optional color)
+        set_normal_color();
+        printf("%-30s %-6s %-12s %-10ld %-20s\n",
+               f->name, type, perms, size, mod_time);
+      }
+      printf("\n");
+}
+
+
 /* Setup signal handlers if INIT is true,
    otherwise restore to the default.  */
 
@@ -1844,7 +1956,19 @@
       j = interrupt_signal;
       if (j)
         raise (j);
+    }
+    /* --count: show number of files, directories, and symlinks */
+  if (count_mode)
+  {
+    
+    count_elements_in_container();
+
+    if (count_mode_with_list)
+    {
+       containers_list();
     }
+  }
+
 
   if (dired)
     {
@@ -2124,8 +2248,17 @@
 
         case AUTHOR_OPTION:
           print_author = true;
+          break;
+        
+        case COUNT_OPTION:
+          count_mode = true;
           break;
 
+        case COUNT_OPTION_WITH_LIST:
+          count_mode = true;
+          count_mode_with_list = true;
+          break;
+
         case HIDE_OPTION:
           {
             struct ignore_pattern *hide = xmalloc (sizeof *hide);
@@ -3097,7 +3230,7 @@
                      "sort_type == sort_none" for its initialization
                      of the sorted_file vector.  */
                   sort_files ();
-                  print_current_files ();
+                  if (!count_mode) print_current_files ();
                   clear_files ();
                 }
             }
@@ -3146,7 +3279,7 @@
     }
 
   if (cwd_n_used)
-    print_current_files ();
+    if (!count_mode) print_current_files ();
 }
 
 /* Add 'pattern' to the list of patterns for which files that match are
@@ -5588,7 +5721,19 @@
 \n\
 \n\
 "), stdout);
+fputs (_("\
+  --count                    will print total counts of files, dirs, and links before listing.\
+  \n\
+"),
+       stdout);
       fputs (_("\
+  --count-list               will print counts of files, dirs and links and \n\
+                             also list down all the containing files, dirs and links for current directory.\
+      \n\
+      \n\
+"), 
+       stdout);
+      fputs (_("\
   -Q, --quote-name           enclose entry names in double quotes\n\
 "), stdout);
       fputs (_("\
NEWS-for-count.patch (application/octet-stream, 1.2 KB)
--- /Users/debkantamondal/coreutils-original/NEWS	2023-04-18 19:38:11
+++ /Users/debkantamondal/coreutils-9.3/NEWS	2025-10-29 00:28:04
@@ -156,6 +156,17 @@
   ls --color now matches a file extension case sensitively
   if there are different sequences defined for separate cases.
 
+  ls --count will count number of directories, files and symlinks
+  of current directory user present. and --count-list will print the
+  count and also print containing items details - like name, size,
+  permissions, modified datetime, and its type. With --count, you get
+  everything in one place: directories, files, links, and the table,
+  without needing to chain commands like ls | wc. It’s simpler, more reliable,
+  and avoids issues with pipes or parsing output. And --count-list can
+  give a detailed table of contained elements with type wise count and 
+  all within the ls , just using options flag , no need extra pipeline/
+  complex command for this simple and frequently required output
+
   printf unicode \uNNNN, \UNNNNNNNN syntax, now supports all valid
   unicode code points.  Previously is was restricted to the C
   universal character subset, which restricted most points <= 0x9F.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.