ls filters by filename - leading dot -a -A or --ignore pattern
I have shell script that just shows directories by interposing `test`
between two calls to ls in a pipeline to give me ls like behavior. Ls
actually knows the filetype so I thought why not just filter on it in ls
given filtering is something ls does? I noted this was not a rejected
feature request and thought it might go well as a request accompanied by a
patch.

--just
was the best switch I could think of to achieve this end. I could easily be
convinced there exists a better one. (--show-only? --showing?)

examples:
just list the block device files


./ls --just b /dev
loop0  loop3  loop6  ram1   ram12  ram15  ram4    ram7  sda   sda3  sda6
sda9
loop1  loop4  loop7  ram10  ram13  ram2   ram5    ram8  sda1  sda4  sda7
sdb
loop2  loop5  ram0   ram11  ram14  ram3   ram6    ram9  sda2  sda5  sda8

./ls --just=normal
ABOUT-NLS    config.log     NEWS
aclocal.m4    config.status  README
AUTHORS        configure      README-hacking
bootstrap    configure.ac   README-package-renamed-to-coreutils
bootstrap.conf    COPYING        README-prereq
cfg.mk        dist-check.mk  README-release
ChangeLog    HACKING        README-valgrind
ChangeLog-2005    init.cfg       thanks-gen
ChangeLog-2006    Makefile       THANKS.in
ChangeLog-2007    Makefile.am    THANKStt.in
ChangeLog-2008    Makefile.in    TODO

can filter on two types by applying the switch twice.

./src/ls --just=normal --just=symbolic-links -l test
total 0
lrwxrwxrwx 1 hal hal 13 Nov 29 00:20 link-to-somefile -> test/somefile
-rw-rw-r-- 1 hal hal  0 Nov 29 00:20 somefile


Why might rejection of this feature and patch be a good idea?
You can get this kind of thing done (sort of) with
$ find . -type d --maxdepth=1 -ls
or shell globbing abuse eg
$ ls -d */
but obviously such things are not ls and lose the familiar and consistent
ls options such as find displaying a differing long format, no colored
output, sorting, control of display of dotfiles etc. However all of these
alternatives' shortcomings can be alleviated with fairly ordinary shell
pipelines involving sed and/or test at the cost of a simple, robust and
convenient user interface as provided by ls.

Shortcomings/BUGS/Possible future enhancements :
1) doesn't work with -R for anything except directories
2) Doesn't have a mode to filter based on permissions (eg show only
executables or setuid etc).
3) Doesn't follow symbolic links and then filter them based on the type of
file they are pointing at and I haven't yet worked out how to add the
command interface for "including symlinks to" in a way that is not too ugly.
4) Others that exist of which I haven't considered.

On the off chance that there does happen to be interest in this feature and
patch by coreutils hackers, I am more than happy to assign the copyright to
GNU on the understanding it will be published under the appropriate version
of the GPL for coreutils.
The patch should apply cleanly to the current default git checkout. I'm
subscribed to the list and interested in any and all feedback.

Thank you for taking the time to give this request an appropriate level of
consideration.

Kind regards,
Hal Ashburner
diff --git a/src/ls.c b/src/ls.c
index e7d1d93..28be236 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -252,6 +252,7 @@ static bool print_color_indicator (const struct fileinfo *f,
                                    bool symlink_target);
 static void put_indicator (const struct bin_str *ind);
 static void add_ignore_pattern (const char *pattern);
+static void do_not_ignore_filetype (const enum filetype f);
 static void attach (char *dest, const char *dirname, const char *name);
 static void clear_files (void);
 static void extract_dirs_from_files (char const *dirname,
@@ -666,6 +667,9 @@ static struct ignore_pattern *ignore_patterns;
    variable itself to be ignored.  */
 static struct ignore_pattern *hide_patterns;
 
+static bool ignore_filetypes;
+static bool filetype_ignored[arg_directory + 1]; 
+
 /* True means output nongraphic chars in file names as '?'.
    (-q, --hide-control-chars)
    qmark_funny_chars and the quoting style (-Q, --quoting-style=WORD) are
@@ -789,6 +793,7 @@ enum
   FULL_TIME_OPTION,
   GROUP_DIRECTORIES_FIRST_OPTION,
   HIDE_OPTION,
+  JUST_FILETYPE_OPTION,
   INDICATOR_STYLE_OPTION,
   QUOTING_STYLE_OPTION,
   SHOW_CONTROL_CHARS_OPTION,
@@ -826,6 +831,7 @@ static struct option const long_options[] =
    DEREFERENCE_COMMAND_LINE_SYMLINK_TO_DIR_OPTION},
   {"hide", required_argument, NULL, HIDE_OPTION},
   {"ignore", required_argument, NULL, 'I'},
+  {"just", required_argument, NULL, JUST_FILETYPE_OPTION},
   {"indicator-style", required_argument, NULL, INDICATOR_STYLE_OPTION},
   {"dereference", no_argument, NULL, 'L'},
   {"literal", no_argument, NULL, 'N'},
@@ -894,6 +900,33 @@ static enum color_type const color_types[] =
 };
 ARGMATCH_VERIFY (color_args, color_types);
 
+static char const *const just_filetype_args[] =
+{
+    "f", "fifos",
+    "c", "character-devices",
+    "d", "directories",
+    "b", "block-devices",
+    "n", "normal",
+    "l", "symbolic-links",
+    "s", "sockets",
+    "w", "whiteouts",
+    "a", "arg-directories",
+    NULL
+};
+static enum filetype const just_filetype_types[] =
+{
+    fifo, fifo,
+    chardev, chardev,
+    directory, directory,
+    blockdev, blockdev,
+    normal, normal,
+    symbolic_link, symbolic_link,
+    sock, sock,
+    whiteout, whiteout,
+    arg_directory, arg_directory
+};
+ARGMATCH_VERIFY (just_filetype_args, just_filetype_types);
+
 /* Information about filling a column.  */
 struct column_info
 {
@@ -1640,6 +1673,14 @@ decode_switches (int argc, char **argv)
           }
       }
   }
+  {
+      ignore_filetypes = false;
+      int i;
+      for (i = 0; i != arg_directory + 1; ++i)
+        {
+          filetype_ignored[i] = true; 
+        }
+  }
 
   while (true)
     {
@@ -1865,6 +1906,15 @@ decode_switches (int argc, char **argv)
           }
           break;
 
+        case JUST_FILETYPE_OPTION:
+          {
+            enum filetype just_filetype = XARGMATCH ("--just", optarg, 
+                                                     just_filetype_args, 
+                                                     just_filetype_types);
+            do_not_ignore_filetype(just_filetype);
+          }
+          break;
+
         case SORT_OPTION:
           sort_type = XARGMATCH ("--sort", optarg, sort_args, sort_types);
           sort_type_specified = true;
@@ -2503,6 +2553,23 @@ queue_directory (char const *name, char const *realname, bool command_line_arg)
   pending_dirs = new;
 }
 
+/* set  this filetype to be paid attention to */
+static void
+do_not_ignore_filetype(const enum filetype ftype)
+{
+    ignore_filetypes = true;
+    filetype_ignored[ftype] = false;
+}
+
+/* Return true if this filetype should be ignored.  */
+static bool
+is_filetype_ignored(enum filetype ftype)
+{
+    return ignore_filetypes && filetype_ignored[ftype];
+}
+
+
+
 /* Read directory NAME, and list the files in it.
    If REALNAME is nonzero, print its name instead of NAME;
    this is used for symbolic links to directories.
@@ -2598,6 +2665,10 @@ print_dir (char const *name, char const *realname, bool command_line_arg)
                 case DT_WHT:  type = whiteout;		break;
 # endif
                 }
+              if (is_filetype_ignored(type))
+                {
+                    continue;
+                }
 #endif
               total_blocks += gobble_file (next->d_name, type,
                                            RELIABLE_D_INO (next),
@@ -4816,6 +4887,11 @@ Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.\n\
   -i, --inode                print the index number of each file\n\
   -I, --ignore=PATTERN       do not list implied entries matching shell PATTERN\
 \n\
+  --just=FILETYPE            only list implied entries of FILETYPE,  filetyes:\n\
+                               arg-directories block-devices character-devices\n\
+                               directories fifos normal symbolic-links sockets\n\
+                               whiteouts\n\
+\n\
   -k, --kibibytes            default to 1024-byte blocks for disk usage\n\
 "), stdout);
       fputs (_("\

Reply via email to