is it possible to use rm to remove files and directories matching a pattern recursively without using other commands?
5 Answers
To directly answer your question, "no - you can't do what you describe with rm".
You can, however, do it you combine it with find. Here's one of many ways you could do that:
# search for everything in this tree, search for the file pattern, pipe to rm
find . | grep <pattern> | xargs rm
For example, if you want to nuke all *~ files, you could so this:
# the $ anchors the grep search to the last character on the line
find . -type f | grep '~'$ | xargs rm
To expand from a comment*:
# this will handle spaces of funky characters in file names
find -type f -name '*~' -print0 | xargs -0 rm
-
IMO: This is the best answer because you can preview the files that will be deleted prior to them being deleted. – monksy Oct 27 '09 at 05:36
-
1true - if you leave-out the last pipe, you'll get a list of everything first :) – warren Oct 27 '09 at 05:48
-
@steven And yet, it didn't actually answer the poster question – A Dwarf Oct 27 '09 at 13:05
-
so, my -1 to this one – A Dwarf Oct 27 '09 at 13:06
-
2May not directly answer the poster's question, but is the closest they will get to what they want. – Drakia Oct 27 '09 at 16:35
-
1A Dwarf, isn't that a little bit bitter for no reason ? – Gnoupi Oct 27 '09 at 16:53
-
The user post a simple question. Can he do it with only the rm command? He didn't ask how he could do it. For all that matters he can know other ways he can do it. And yet, perfectly valid answers to his question had been downvoted for no clear reason. Why shouldn't I downvote an answer that makes no effort to answer the actual question? – A Dwarf Oct 27 '09 at 17:42
-
the answer is "no - you can't do what you describe with `rm`". I showed him how he *could* do it if he wants to. – warren Oct 28 '09 at 03:40
-
10Please be very careful using `find | grep | xargs rm`. If there are files with spaces (or newlines), this will break (and depending on the filenames and where the spaces are) might delete stuff that you did not intend to delete. `find … -print0 | xargs -0 rm` will be much more robust. It will mean, however that you cannot use `grep` and must use `find`'s predicates to match and print0 only the desired files. warren's second example will be more robust as `find -type f -name '*~' -print0 | xargs -0 rm`. – Chris Johnsen Oct 28 '09 at 05:20
-
@Chris - updated my answer – warren Oct 28 '09 at 09:00
-
@warren after your update, removed my downvote – A Dwarf Oct 28 '09 at 18:35
-
1If you want a single command to do the job, make an alias using one of the find commands given. Will fill in an answer for this later, if desired. – casualuser Nov 07 '09 at 18:09
-
You don't need funkier characters than a space to kill your first examples, and potentially delete other files than what is wanted. I recommend you change them to at least use `xargs -d'\n'` to allow spaces. But the two first examples are trumped by your last example, so perhaps just skip them. They are slower and less reliable. – Daniel Andersson May 16 '12 at 13:48
"without using other commands"
No.
- 655
- 3
- 5
-
Nice answer illustrating the "strictly answer the initial question (at the risk of not being able to provide a solution)" vs. "provide a solution, even if it's not strictly matching to imposed restrictions" debate. – Gnoupi Oct 27 '09 at 16:59
-
I only posted this as "A Dwarf" was complaining about the answer that actually provided a solution. Without using other commands there really is no way to do recursive **file** deletion that matches a pattern, just current-directory file/directory deletion. – Drakia Oct 27 '09 at 18:29
Using Bash, with globstar set, yes:
rm basedir/**/my*pattern*
Try it with e.g. ls -1 first, before rm to list the files you match.
You set options through e.g. shopt -s globstar.
Alternatively, a shorter find variant:
find -type f -name 'my*pattern*' -delete
or for GNU find:
find -type f -name 'my*pattern*' -exec rm {} +
or another alternative for non-GNU find (a bit slower):
find -type f -name 'my*pattern*' -exec rm {} \;
To also remove directories, as you ask for: just change rm into rm -r in the above commands and skip matching on only -type f in the find commands.
- 23,895
- 5
- 57
- 61
If you use zsh(1), turn on "extended globbing" with setopt extendedglob in .zshrc. Prefixing the pattern with '**/' will then delete recursively:
% rm -rf **/< pattern >
However, if there are a lot of files to delete you should resort to find(1) with xargs(1) or -exec, and I also recommend doing that in shell scripts.
- 116
- 3
I would have asuumed " rm -rf " where is a combination of file names, and matching patterns such as * and ? etc (eg todays_log_2009????.log) . That will start from current Dir and work down recursively removing files that macth that pattern.
- 990
- 4
- 11
- 18
-
This won't work because the pattern is expanded by the shell in the current directory. If quoted, the pattern becomes a filename with special characters in it. e.g. to delete the file [, one could write rm '[' . The pattern simply loses its meaning. – casualuser Nov 07 '09 at 18:02