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 (_("\