bash - Why backslash before asterisk in `find`?
2014-07
In this command:
find . -name \*.pyc -delete
Why is a backslash needed before *.pyc
?
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
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.
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?
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.
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.
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