42

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?

1
  • 1
    No, 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
26

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 *
4
  • 23
    Doesn't answer the question? (what if I want to recurse to a depth of 2) – Steven Lu Aug 25 '15 at 17:13
  • Good point, I missed that. Any suggestions? – Eric Wilson Aug 25 '15 at 21:33
  • @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 2 '20 at 13:48
  • Cool. FWIW I don't use ack anymore, ripgrep is where it's at. – Steven Lu Nov 2 '20 at 20:38
45

You can couple find with the -exec argument. example:

find . -maxdepth 1 -exec grep foo {} \;

This can be scaled, i.e. -maxdepth 2

7
  • 1
    Stephane, 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
  • it will not reach @stephane if you don't use the @. – Braiam Jan 31 '14 at 5:26
  • 5
    Yes 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 6:57
  • 3
    Also 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 7:01
  • 5
    I 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

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:

  • zsh and GNU grep or compatible:

    grep -H foo ./*(.D)
    
  • standard find and grep from any shell:

    find . ! -name . -prune -type f -exec grep foo /dev/null {} +
    
  • GNU find and GNU grep (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 find and GNU grep (or compatible) from any shell:

    find . -maxdepth 3 -type f -exec grep -H foo {} +
    
  • standard find and grep, but assuming file names are valid text in the locale:

    find . '(' ! -path './*/*/*' -o -prune ')' -o -exec grep foo /dev/null {} +
    
  • zsh and GNU grep or 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...

0

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.

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.