[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] grep: -r with no args now searches "."
From: |
Paul Eggert |
Subject: |
[PATCH] grep: -r with no args now searches "." |
Date: |
Mon, 02 Jan 2012 04:22:52 -0800 |
User-agent: |
Mozilla/5.0 (X11; Linux i686; rv:8.0) Gecko/20111124 Thunderbird/8.0 |
This is a patch I've been meaning to write for years.
Currently, one must write "grep -r PAT ." to search the working
directory recursively, and that trailing " ." is an annoyance.
When I added support for "grep -r", I forgot to have "grep -r PAT"
search the working directory by default, instead of searching
standard input (which makes no sense, even if stdin is a directory).
This is not an upward compatible change, since "grep -r PAT <file"
will no longer search standard input, but that's OK; nobody should
be using "grep -r" that way anyway.
* NEWS: Document this.
* doc/grep.texi (File and Directory Selection, grep Programs, Usage):
Likewise.
* src/main.c (usage): Likewise.
(grepdir): If DIR is null, search the working directory, but do
not prepend "./" to the file names.
(main): If recursing and no operands are given, search ".".
* tests/Makefile.am (TESTS): Add r-dot.
* tests/r-dot: New file.
---
NEWS | 3 +++
doc/grep.texi | 13 ++++++-------
src/main.c | 48 +++++++++++++++++++++++++++++++++++-------------
tests/Makefile.am | 1 +
tests/r-dot | 14 ++++++++++++++
5 files changed, 59 insertions(+), 20 deletions(-)
create mode 100755 tests/r-dot
diff --git a/NEWS b/NEWS
index d4475bc..e729e1b 100644
--- a/NEWS
+++ b/NEWS
@@ -35,6 +35,9 @@ GNU grep NEWS -*- outline
-*-
** New features
+ If no file operands are given, grep -r now searches the working directory.
+ Formerly it ignored the -r and searched standard input nonrecursively.
+
grep now supports color highlighting of matches on MS-Windows.
* Noteworthy changes in release 2.10 (2011-11-16) [stable]
diff --git a/doc/grep.texi b/doc/grep.texi
index 9889095..75980e0 100644
--- a/doc/grep.texi
+++ b/doc/grep.texi
@@ -669,7 +669,7 @@ Search only files whose base name matches @var{glob}
@opindex --recursive
@cindex recursive search
@cindex searching directory trees
-For each directory mentioned on the command line,
+For each directory operand,
read and process all files in that directory, recursively.
This is the same as the @samp{--directories=recurse} option.
@@ -1010,10 +1010,12 @@ instead of strict equality with@ 2.
@cindex variants of @command{gerp}
@command{grep} searches the named input files
-(or standard input if no files are named,
-or the file name @file{-} is given)
for lines containing a match to the given pattern.
By default, @command{grep} prints the matching lines.
+A file named @file{-} stands for standard input.
+If no files are named, a recursive @command{grep}
+searches the working directory @file{.}, and a
+nonrecursive @command{grep} searches standard input.
There are four major variants of @command{grep},
controlled by the following options.
@@ -1492,14 +1494,11 @@ find /home/gigi -name '*.c' -print0 | xargs -0r grep -H
'hello'
This differs from the command:
@example
-grep -rH 'hello' *.c
+grep -H 'hello' *.c
@end example
which merely looks for @samp{hello} in all files in the current
directory whose names end in @samp{.c}.
-Here the @option{-r} is
-probably unnecessary, as recursion occurs only in the unlikely event
-that one of @samp{.c} files is a directory.
The @samp{find ...} command line above is more similar to the command:
@example
diff --git a/src/main.c b/src/main.c
index a1d590a..79d037f 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1348,6 +1348,7 @@ grepfile (char const *file, struct stats *stats)
static int
grepdir (char const *dir, struct stats const *stats)
{
+ char const *dir_or_dot = (dir ? dir : ".");
struct stats const *ancestor;
char *name_space;
int status = 1;
@@ -1372,38 +1373,50 @@ grepdir (char const *dir, struct stats const *stats)
}
}
- name_space = savedir (dir, stats->stat.st_size, included_patterns,
+ name_space = savedir (dir_or_dot, stats->stat.st_size, included_patterns,
excluded_patterns, excluded_directory_patterns);
if (! name_space)
{
if (errno)
- suppressible_error (dir, errno);
+ suppressible_error (dir_or_dot, errno);
else
xalloc_die ();
}
else
{
- size_t dirlen = strlen (dir);
- int needs_slash = ! (dirlen == FILE_SYSTEM_PREFIX_LEN (dir)
- || ISSLASH (dir[dirlen - 1]));
- char *file = NULL;
+ size_t dirlen = 0;
+ int needs_slash = 0;
+ char *file_space = NULL;
char const *namep = name_space;
struct stats child;
+ if (dir)
+ {
+ dirlen = strlen (dir);
+ needs_slash = ! (dirlen == FILE_SYSTEM_PREFIX_LEN (dir)
+ || ISSLASH (dir[dirlen - 1]));
+ }
child.parent = stats;
out_file += !no_filenames;
while (*namep)
{
size_t namelen = strlen (namep);
- file = xrealloc (file, dirlen + 1 + namelen + 1);
- strcpy (file, dir);
- file[dirlen] = '/';
- strcpy (file + dirlen + needs_slash, namep);
+ char const *file;
+ if (! dir)
+ file = namep;
+ else
+ {
+ file_space = xrealloc (file_space, dirlen + 1 + namelen + 1);
+ strcpy (file_space, dir);
+ file_space[dirlen] = '/';
+ strcpy (file_space + dirlen + needs_slash, namep);
+ file = file_space;
+ }
namep += namelen + 1;
status &= grepfile (file, &child);
}
out_file -= !no_filenames;
- free (file);
+ free (file_space);
free (name_space);
}
@@ -1509,8 +1522,9 @@ Context control:\n\
\n"));
fputs (_(after_options), stdout);
printf (_("\
-With no FILE, or when FILE is -, read standard input. If less than two
FILEs\n\
-are given, assume -h. Exit status is 0 if any line was selected, 1
otherwise;\n\
+When FILE is -, read standard input. With no FILE, read '.' if recursive,\n\
+standard input if not. If fewer than two FILEs are given, assume -h.\n\
+Exit status is 0 if any line was selected, 1 otherwise;\n\
if any error occurs and -q was not given, the exit status is 2.\n"));
printf (_("\nReport bugs to: %s\n"), PACKAGE_BUGREPORT);
printf (_("GNU Grep home page: <%s>\n"),
@@ -2233,6 +2247,14 @@ main (int argc, char **argv)
}
while (++optind < argc);
}
+ else if (directories == RECURSE_DIRECTORIES)
+ {
+ status = 1;
+ if (stat (".", &stats_base.stat) == 0)
+ status = grepdir (NULL, &stats_base);
+ else
+ suppressible_error (".", errno);
+ }
else
status = grepfile ((char *) NULL, &stats_base);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index df98e0b..77b670b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -73,6 +73,7 @@ TESTS = \
pcre-abort \
pcre-z \
prefix-of-multibyte \
+ r-dot \
reversed-range-endpoints \
sjis-mb \
spencer1 \
diff --git a/tests/r-dot b/tests/r-dot
new file mode 100755
index 0000000..73e593c
--- /dev/null
+++ b/tests/r-dot
@@ -0,0 +1,14 @@
+#!/bin/sh
+# Check that "grep -r PAT" reads ".".
+. "${srcdir=.}/init.sh"; path_prepend_ ../src
+
+mkdir dir || framework_failure_
+echo aaa > dir/a || framework_failure_
+echo bbb > dir/b || framework_failure_
+
+echo a:aaa > exp || framework_failure_
+
+(cd dir && grep -r aaa) > out || fail=1
+compare exp out || fail=1
+
+Exit $fail
--
1.7.6.4
- [PATCH] grep: -r with no args now searches ".",
Paul Eggert <=