bash - Why backslash before asterisk in `find`?

07
2014-07
  • Ram Rachum

    In this command:

    find . -name \*.pyc -delete
    

    Why is a backslash needed before *.pyc ?

  • Answers
  • devnull

    An unquoted glob would be expanded by the shell before find is executed. (Refer to Filename Expansion in the manual.)

    So saying:

    find . -name *.pyc -delete
    

    would actually execute:

    find . -name file1.pyc file2.pyc file3.pyc -delete
    

    assuming there were 3 .pyc files in the current directory and result in an error instead.

    A backslash makes the shell pass the glob to find, i.e. it acts as if *.pyc were quoted.

    Ideally, you should be quoting a glob:

    find . -name '*.pyc' -delete
    
  • terdon

    Before your shell issues the find command, it will do various expansions. Doing so, it also processes special characters (or, characters with special meaning), where * is a wildcard – a globbing character. This is the so-called filename expansion.

    Say you have two files in your directory:

    • foo.pyc
    • bar.pyc

    Then *.pyc would expand to both names. So if you write:

    find . -name *.pyc -delete
    

    then the shell will actually call:

    find . -name foo.pyc bar.pyc -delete
    

    which does not make a lot of sense, because you can only have one argument for -name. That's why you need to escape the special character to prevent it from being interpreted by the shell. You do that by backslash-escaping, or alternatively, quoting it.


  • Related Question

    bash - avoid permission denied spam when using find-command
  • user40167

    I often try to find files with following syntax:

    find . -name "filetofind"
    

    However it usually results as many rows or error reporting (Permission denied) about folders where permission is denied. Is there any other way to avoid this spam than using sudo or advanced grepping from error-output?


  • Related Answers
  • whitequark

    Try

    find . -name "filetofind" 2>/dev/null
    

    This will redirect stderr output stream, which is used to report all errors, including "Access denied" one, to null device.

  • Hogan

    If you want to see other errors and you don't have files named "permission denied" then this will work "better".

    find . -name "filetofind" 2>&1 | grep -v 'permission denied' 
    

    Redirecting the output to grep with the inversion option.

  • sdaau

    You can also use the -perm and -prune predicates to avoid descending into unreadable directories (see also How do I remove "permission denied" printout statements from the find program? - Unix & Linux Stack Exchange):

    find . -type d ! -perm -g+r,u+r,o+r -prune -o -name "filetofind" -print