summaryrefslogtreecommitdiff
path: root/src/ls.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2004-09-26 22:56:38 +0000
committerPaul Eggert <eggert@cs.ucla.edu>2004-09-26 22:56:38 +0000
commit92b1470e88cb69d8f50235b79f87fab5ac44c2cb (patch)
tree477b3686f8e7dff53587829f87bd31c9ce440ce5 /src/ls.c
parentb7cffb8c5e9be5f1b1295449180285686430a93c (diff)
downloadcoreutils-92b1470e88cb69d8f50235b79f87fab5ac44c2cb.tar.xz
Add "ls --hide".
(file_ignored): Renamed from file_interesting, with inverted return value. Accept the file name, not a struct dirent *. All uses changed. Avoid the expense of calling fnmatch if the file is ignorable due to leading '.'. (all_files, really_all_files): Removed; replaced by: (ignore): New variable. All uses changed. (IGNORE_DEFAULT, IGNORE_DOT_AND_DOTDOT, IGNORE_MINIMAL, HIDE_OPTION): New constants. (hide_patterns): New variable. (long_options, decode_switches, file_ignored, usage): Add support for --hide. (patterns_match): New function. (usage): Replace "hide" with "ignore" in explanation, to avoid confusion.
Diffstat (limited to 'src/ls.c')
-rw-r--r--src/ls.c93
1 files changed, 59 insertions, 34 deletions
diff --git a/src/ls.c b/src/ls.c
index f0e445a4a..38cb2fea9 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -232,7 +232,7 @@ static size_t quote_name (FILE *out, const char *name,
size_t *width);
static char *make_link_path (const char *path, const char *linkname);
static int decode_switches (int argc, char **argv);
-static bool file_interesting (const struct dirent *next);
+static bool file_ignored (char const *name);
static uintmax_t gobble_file (const char *name, enum filetype type,
bool explicit_arg, const char *dirname);
static void print_color_indicator (const char *name, mode_t mode, int linkok);
@@ -572,17 +572,23 @@ static bool recursive;
static bool immediate_dirs;
-/* True means don't omit files whose names start with `.'. -A */
+/* Which files to ignore. */
-static bool all_files;
-
-/* True means don't omit files `.' and `..'
- This flag implies `all_files'. -a */
-
-static bool really_all_files;
+static enum
+{
+ /* Ignore files whose names start with `.', and files specified by
+ --hide and --ignore. */
+ IGNORE_DEFAULT,
+
+ /* Ignore `.', `..', and files specified by --ignore. */
+ IGNORE_DOT_AND_DOTDOT,
+
+ /* Ignore only files specified by --ignore. */
+ IGNORE_MINIMAL
+} ignore;
/* A linked list of shell-style globbing patterns. If a non-argument
- file name matches any of these patterns, it is omitted.
+ file name matches any of these patterns, it is ignored.
Controlled by -I. Multiple -I options accumulate.
The -B option adds `*~' and `.*~' to this list. */
@@ -594,6 +600,10 @@ struct ignore_pattern
static struct ignore_pattern *ignore_patterns;
+/* Similar to IGNORE_PATTERNS, except that -a or -A causes this
+ variable itself to be ignored. */
+static struct ignore_pattern *hide_patterns;
+
/* 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
@@ -682,6 +692,7 @@ enum
DEREFERENCE_COMMAND_LINE_SYMLINK_TO_DIR_OPTION,
FORMAT_OPTION,
FULL_TIME_OPTION,
+ HIDE_OPTION,
INDICATOR_STYLE_OPTION,
QUOTING_STYLE_OPTION,
SHOW_CONTROL_CHARS_OPTION,
@@ -715,6 +726,7 @@ static struct option const long_options[] =
{"dereference-command-line", no_argument, 0, 'H'},
{"dereference-command-line-symlink-to-dir", no_argument, 0,
DEREFERENCE_COMMAND_LINE_SYMLINK_TO_DIR_OPTION},
+ {"hide", required_argument, 0, HIDE_OPTION},
{"ignore", required_argument, 0, 'I'},
{"indicator-style", required_argument, 0, INDICATOR_STYLE_OPTION},
{"dereference", no_argument, 0, 'L'},
@@ -1348,9 +1360,9 @@ decode_switches (int argc, char **argv)
dereference = DEREF_UNDEFINED;
recursive = false;
immediate_dirs = false;
- all_files = false;
- really_all_files = false;
- ignore_patterns = 0;
+ ignore = IGNORE_DEFAULT;
+ ignore_patterns = NULL;
+ hide_patterns = NULL;
/* FIXME: put this in a function. */
{
@@ -1432,8 +1444,7 @@ decode_switches (int argc, char **argv)
switch (c)
{
case 'a':
- all_files = true;
- really_all_files = true;
+ ignore = IGNORE_MINIMAL;
break;
case 'b':
@@ -1450,8 +1461,7 @@ decode_switches (int argc, char **argv)
case 'f':
/* Same as enabling -a -U and disabling -l -s. */
- all_files = true;
- really_all_files = true;
+ ignore = IGNORE_MINIMAL;
sort_type = sort_none;
sort_type_specified = true;
/* disable -l */
@@ -1544,8 +1554,8 @@ decode_switches (int argc, char **argv)
break;
case 'A':
- really_all_files = false;
- all_files = true;
+ if (ignore == IGNORE_DEFAULT)
+ ignore = IGNORE_DOT_AND_DOTDOT;
break;
case 'B':
@@ -1633,6 +1643,15 @@ decode_switches (int argc, char **argv)
print_author = true;
break;
+ case HIDE_OPTION:
+ {
+ struct ignore_pattern *hide = xmalloc (sizeof *hide);
+ hide->pattern = optarg;
+ hide->next = hide_patterns;
+ hide_patterns = hide;
+ }
+ break;
+
case SORT_OPTION:
sort_type = XARGMATCH ("--sort", optarg, sort_args, sort_types);
sort_type_specified = true;
@@ -2245,7 +2264,7 @@ print_dir (const char *name, const char *realname)
break;
}
- if (file_interesting (next))
+ if (! file_ignored (next->d_name))
{
enum filetype type = unknown;
@@ -2326,25 +2345,29 @@ add_ignore_pattern (const char *pattern)
ignore_patterns = ignore;
}
-/* Return true if the file in `next' should be listed. */
+/* Return true if one of the PATTERNS matches FILE. */
static bool
-file_interesting (const struct dirent *next)
+patterns_match (struct ignore_pattern const *patterns, char const *file)
{
- register struct ignore_pattern *ignore;
-
- for (ignore = ignore_patterns; ignore; ignore = ignore->next)
- if (fnmatch (ignore->pattern, next->d_name, FNM_PERIOD) == 0)
- return false;
+ struct ignore_pattern const *p;
+ for (p = patterns; p; p = p->next)
+ if (fnmatch (p->pattern, file, FNM_PERIOD) == 0)
+ return true;
+ return false;
+}
- if (really_all_files
- || next->d_name[0] != '.'
- || (all_files
- && next->d_name[1] != '\0'
- && (next->d_name[1] != '.' || next->d_name[2] != '\0')))
- return true;
+/* Return true if FILE should be ignored. */
- return false;
+static bool
+file_ignored (char const *name)
+{
+ return ((ignore != IGNORE_MINIMAL
+ && name[0] == '.'
+ && (ignore == IGNORE_DEFAULT || ! name[1 + (name[1] == '.')]))
+ || (ignore == IGNORE_DEFAULT
+ && patterns_match (hide_patterns, name))
+ || patterns_match (ignore_patterns, name));
}
/* POSIX requires that a file size be printed without a sign, even
@@ -3997,7 +4020,7 @@ Sort entries alphabetically if none of -cftuSUX nor --sort.\n\
Mandatory arguments to long options are mandatory for short options too.\n\
"), stdout);
fputs (_("\
- -a, --all do not hide entries starting with .\n\
+ -a, --all do not ignore entries starting with .\n\
-A, --almost-all do not list implied . and ..\n\
--author print the author of each file\n\
-b, --escape print octal escapes for nongraphic characters\n\
@@ -4035,6 +4058,8 @@ Mandatory arguments to long options are mandatory for short options too.\n\
--dereference-command-line-symlink-to-dir\n\
follow each command line symbolic link\n\
that points to a directory\n\
+ --hide=PATTERN do not list implied entries matching shell PATTERN\n\
+ (overridden by -a or -A)\n\
"), stdout);
fputs (_("\
--indicator-style=WORD append indicator with style WORD to entry names:\n\