Is there any way to tell ack to only search for text on the current folder? (or specify a max-depth level?) And with grep?
- 35,380
- 25
- 108
- 167
- 40,169
- 77
- 197
- 294
-
1No, ack does not have a max-depth option, other than the `-n` to not recurse at all. – Andy Lester Apr 24 '14 at 14:41
4 Answers
You can couple find with the -exec argument. Example:
find . -maxdepth 1 -exec grep foo {} \;
This can be scaled, i.e. -maxdepth 2.
Edit
As mentioned in the [answer by @Stéphane Chazelas], it is advisable to restrict find to regular files so that grep doesn't produce an error when the argument {} actually is a directory path:
find . -maxdepth 1 -type f -exec grep -H foo {} \;
-type fis a filter forfindthat limits the search results to files-His agrepoption used to print a filename for every match (desired behavior when more than one file match)
- 21,637
- 21
- 47
- 71
- 1,030
- 7
- 16
-
1Stephane, my answer (`-maxdepth 1`) was scaleable. For example `-maxdepth 2`. I do not know how to describe the edit you made as such. – David Wilkins Jan 30 '14 at 20:15
-
-
6Yes sorry, I agree my edit was too much intrusive. You may still want to clarify that that (`-maxdepth`) is not portable/standard syntax (only GNU and some BSDs). Also, there's no point using `\;` here (run one `grep` per file). Use `grep -H foo {} +` (GNU specific) or `grep foo /dev/null {} +` (standard) to make sure the file name is always printed. The standard equivalent to `-maxdepth 2` would be `find . -path './*/*' -type d -prune -o -type f -exec ...` – Stéphane Chazelas Jan 31 '14 at 06:57
-
4Also note that yours will give error messages for directories (including `.` as you don't give the `-mindepth 1`) while GNU `grep` will not try to read directories with `-r` (it _recurses_ on them). You may want to add a `-d skip` to `grep` (assuming GNU grep) or better add `! -type d` to `find` or even better `-type f` (or `-xtype f` assuming GNU `find`) as you probably don't want `grep` to read non-regular files. – Stéphane Chazelas Jan 31 '14 at 07:01
-
6I tend to use `grep -Hin` with this approach so that I can see the filename and the line that the occurrence is on. – GDP2 Apr 11 '16 at 19:41
-
-
1@uav feel free to send a patch to the GNU utils mailing list. The idea behind GNU tools is that each tool should have a limited, specialized set of features and be used in cooperation. GNU `find` has all the features you need to drill down a file system, filtering out anything you don't want. Embedding it within grep, sed and gawk seems like a lot of redundant effort. – sleblanc Nov 02 '20 at 13:39
Use -n for no-recurse:
$ ack -n foo
grep is not recursive by default, and you should use the -r flag only if you want a recursive search.
You can search the current directory with grep as follows:
$ grep -- foo *
- 522,931
- 91
- 1,010
- 1,501
- 4,622
- 9
- 32
- 43
-
26Doesn't answer the question? (what if I want to recurse to a depth of 2) – Steven Lu Aug 25 '15 at 17:13
-
-
@StevenLu, you can recurse a number of directories by using globs: `ack -n pattern */*/`. It has several caveats, like expanding directories with an extreme number of subdirectories. If you make sure that the glob has a slash at the end, then it will only expand directory names, so that should limit the potential for damage, a bit. – sleblanc Nov 02 '20 at 13:48
-
-
where can I find clarification for the syntax 'grep --'? I didn't find it it 'man grep'. – user3804598 Sep 08 '21 at 07:20
-
@user3804598 it's not a `grep` thing, it's a shell thing. From `man bash`: "A -- signals the end of options and disables further option processing. Any arguments after the -- are treated as filenames and arguments." – J.M. Janzen Aug 22 '23 at 20:55
For an equivalent of GNU grep -r foo . that looks only in regular files in the current directory and not any of the subdirectories, you can do:
zshand GNUgrepor compatible:grep -H foo ./*(.D)standard
findandgrepfrom any shell:find . ! -name . -prune -type f -exec grep foo /dev/null {} +GNU
findand GNUgrep(or compatible) from any shell:find . -maxdepth 1 -type f -exec grep -H foo {} +
To look for files at depths 1 to 3 (in ./file, ./subdir/file, ./subdir/subsubdir/file, but not any deeper):
GNU
findand GNUgrep(or compatible) from any shell:find . -maxdepth 3 -type f -exec grep -H foo {} +standard
findandgrep, but assuming file names are valid text in the locale:find . '(' ! -path './*/*/*' -o -prune ')' -o -exec grep foo /dev/null {} +zshand GNUgrepor compatible:set -o extendedglob # best in ~/.zshrc grep -H foo ./**/*~./*/*/*/*(D.)though note that it's inefficient as it still looks for files at any depth before excluding them with the
~extendedglob operator.
-H (GNU extension) / /dev/null is to make sure grep prints the name of the file even if only one file is given to it.
-type f or zsh's . glob qualifier is to select only regular files (like GNU grep does by default with -r nowadays), to the exclusion of all other types of files such as symlinks (even if they point to regular files), directories, fifos, devices...
- 522,931
- 91
- 1,010
- 1,501
I'm obviously late to the topic, but this may prove useful to a future reader. After reading the comments and answers above, perhaps a wrapper script for grep is in order until GNU find gains a -maxdepth option. Using a pattern like the following,
grep -Hin foo `find . -maxdepth 1 -type f`
the following script will effectively wrap the pair of commands:
#! /bin/sh
#
# USAGE: grep-maxdepth <NUM> <GREP_ARGS>
#
# <NUM> integer specifying the maxdepth passed to find
# <GREP_ARGS> arguments provided to grep
#
depth=$1
shift
# DON'T DO THIS ! grep $* `find . -maxdepth ${depth} -type f`
# DO this based upon comments
find . -maxdepth ${depth} -type f -exec grep $* {} \;
This solution should work regardless of the availability of GNU grep; however, the usage of -maxdepth for find implies the installation of GNU's Tools.
I don't use ack, but this simple solution should work for it as well.
NOTE: Trivially-edited based upon comment from Stéphane Chazelas. This should now properly-accommodate white space and other characters in file names. Thanks.
- 21
- 1
- 1
- 5
-
That's wrong for a number of reasons. See [Why is looping over find's output bad practice?](//unix.stackexchange.com/q/321697) and [Security implications of forgetting to quote a variable in bash/POSIX shells](//unix.stackexchange.com/q/171346) for instance. – Stéphane Chazelas Mar 10 '21 at 17:37