I'm trying to remove a lot of files at once but need to be specific as to not remove any of the files I actually need.

I have a ton of corrupt files that start master- but there are valid files that start with master-2018

So, I want to do something like

rm -rf master-* --exclude master-2018*

Is that I need possible?

  • 7
    These files sound important. Why not copy/move the master-2018* files somewhere else first, and then just remove all the rest? – Konrad Rudolph Nov 7 '18 at 10:32

Yes you can use more than one pattern with find:

$ find -name 'master-*' \! -name 'master-2018*' -print0 -prune |
     xargs -0 echo rm -fr

(remove the echo if you're satisfied with the dry run)

You should add a -maxdepth 1 predicate just after find if you only want ro remove files from the current directory, ie master-1991 but no subdir/master-1991.

  • 2
    but the OP is using rm -rf, -delete will only work if the dir is empty. – mosvy Nov 6 '18 at 23:49
  • I'll give this a go and report back, thanks for your help – Dan James Palmer Nov 7 '18 at 0:00
  • 1
    Is there any advantage in using find … -print0 | xargs … over a simple find … -exec or find … -execdir? – Sparhawk Nov 7 '18 at 6:17
  • 2
    @Sparhawk Efficiency. -exec will start a new process for every hit, while xargs will only start one extra process. – Stig Hemmer Nov 7 '18 at 8:59
  • 4
    @Sparhawk yes, the fact that find and xargs are run in parallel. find ... -exec cmd {} + (with the + at the end) will fit as many arguments as it can to cmd (just like xargs), but find will still have to wait for it to finish before proceeding further. The disadvantage of find -print0 | xargs -0 is that is not standard -- it's pretty well supported though (GNU, *BSD, busybox, android, solaris if used with gxargs). – mosvy Nov 7 '18 at 9:17

In bash:

shopt -s extglob
echo rm master-!(2018*)

Remove the echo if it looks correct.

The above uses bash's extended globbing facility to match files that start with master- but who do not have 2018 immediately following, then followed by anything (*).


If all files you want to delete has pattern like master-YYYY*, you can use those patterns:

rm -rf master-???[0-79]*
rm -rf master-??[02-9]*
rm -rf master-?[1-9]*
rm -rf master-[013-9]*

The goal is to ommit digits from a year number, so on first place after master- we need to ommit (don't remove) digit 2, on 2nd place digit 0, on 3rd place digit 1, and on 4th place - digit 8 I tried it just a minute before, and is enough to run only first two of them.

Second method: You can move master-2018 to another dir, e.g. /tmp, then remove everything with master-*, and move back your master-2018 from tmp.

mkdir /tmp/backup
mv -r master-2018* /tmp/backup
rm -rf master-*
mv -r /tmp/backup/* .
  • 1
    Ahh so, rm -rf master-????[2019-9999]* would remove all files from master-2019* to master-9999*? – Dan James Palmer Nov 6 '18 at 23:22
  • No, it not works this way. You can not specify numbers in [ ] braces. Only digits. You specify which digits will be places in the place of [xxxxxxx]. So max possibilities is range from 0 to 9 like this [0-9] or this [0123456789]. This can replace only one character from file name. rob@vps:mast$ ls master-1990 master-1994 master-2006 master-2010 master-2014 master-2018 master-1991 master-1995 master-2007 master-2009 master-2013 master-2017 rob@vps:mast$ rm master-[2000-2019]* rob@vps:mast$ ls empty directory` – Robert Zabkiewicz Nov 6 '18 at 23:27
  • 3
    none of your commands will remove a file with the name master-of-puppets – mosvy Nov 6 '18 at 23:42

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.