I was trying to remove duplicate downloads and made the error of running
rm -rf *(1)*
This deleted everything in ~/Downloads
without an error message.
What exactly does this regex do?
I was trying to remove duplicate downloads and made the error of running
rm -rf *(1)*
This deleted everything in ~/Downloads
without an error message.
What exactly does this regex do?
In a POSIX shell, the parenthesis are reserved for spawning the inner commands (cmd1; cmd2; cmd3)
in a subshell. Since in *(1)*
the parenthesis are not separated from the asterisks by newlines or semicolons,
it is a syntax error. Of course, even *;(1);*
would not make sense,
although not a syntax error per se.
In Bash, if extglob
is enabled, as can be verified with shopt -p |& grep extglob
, "*(pattern-list)
matches zero
or more ocurrences of the given patterns". In this case, *(1)*
always expands to all the files in the directory, since *(1)
can
match zero occurrence of the pattern 1
and *
will match all other
names, whatever they are. The result is that all files (and directories, which are files too) are removed.
Also notice that shells use shell patterns (as known as globs), which are not the same as regular expressions. See Gilles' answer for a detailed more account of that. In your case, to remove every file whose name contains (1)
, you would need to escape or quote the parenthesis to preserve their literal meaning, i.e.,
rm -rf *'(1)'*
rm -rf *\(1\)*
rm -rf *"(1)"*
extglob
option (shortcut:shopt -p |& grep extglob
). – Quasímodo Oct 07 '20 at 16:42$ shopt -p |& grep extglob
yieldsshopt -s extglob
– Warrick Macmillan Oct 07 '20 at 20:52