6

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?

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

3 Answers 3

17

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.

5
  • 2
    but the OP is using rm -rf, -delete will only work if the dir is empty. Commented Nov 6, 2018 at 23:49
  • I'll give this a go and report back, thanks for your help Commented Nov 7, 2018 at 0:00
  • 1
    Is there any advantage in using find … -print0 | xargs … over a simple find … -exec or find … -execdir? Commented Nov 7, 2018 at 6:17
  • 2
    @Sparhawk Efficiency. -exec will start a new process for every hit, while xargs will only start one extra process. Commented Nov 7, 2018 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). Commented Nov 7, 2018 at 9:17
10

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 (*).

0

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/* .
3
  • 1
    Ahh so, rm -rf master-????[2019-9999]* would remove all files from master-2019* to master-9999*? Commented Nov 6, 2018 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` Commented Nov 6, 2018 at 23:27
  • 3
    none of your commands will remove a file with the name master-of-puppets Commented Nov 6, 2018 at 23:42

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.