29

I have many files named

sequence_1_0001.jpg  
sequence_1_0002.jpg  
sequence_1_0003.jpg  
...

and files named

sequence_1_0001.hmf  
sequence_1_0002.hmf  
sequence_1_0003.hmf  
...

and files named

sequence_2_0001.jpg  
sequence_2_0002.jpg  
sequence_2_0003.jpg  
...

and

sequence_2_0001.hmf  
sequence_2_0002.hmf  
sequence_2_0003.hmf  
...

I just want to remove the files that begin with 'sequence_1' and end in '.hmf', but I don't want to remove them one by one, since there are thousands of files. How can I specify to the rm command that I want to remove all that begin with the prefilx 'sequence_1' and end in '.hmf'?

I'm currently working with a RedHat Linux system, but I'd like to know how to do it on other distributions as well.

Braiam
  • 35,991
Paul
  • 9,423

3 Answers3

40
rm sequence_1*.hmf

removes files beginning with sequence_1 and ending with .hmf.


Globbing is the process in which your shell takes a pattern and expands it into a list of filenames matching that pattern. Do not confuse it with regular expressions, which is different. If you spend most of your time in bash, the Wooledge Wiki has a good page on globbing (pathname expansion). If you want maximum portability, you'll want to read the POSIX spec on pattern matching as well / instead.


In the unlikely case you run into an "Argument list too long" error, you can take a look at BashFAQ 95, which addresses this. The simplest workaround is to break up the glob pattern into multiple smaller chunks, until the error goes away. In your case, you could probably get away with splitting the match by prefix digits 0 through 9, as follows:

for c in {0..9}; do rm sequence_1_"$c"*.hmf; done
rm sequence_1*.hmf  # catch-all case
jw013
  • 51,212
  • This is a very clever work around the 'argument list too long' error. In my case, I have twenty thousand files, so I guess I would have to use a for loop from 0,..,20. Right? – Paul Apr 26 '12 at 14:18
  • @Paul Right, just break the list into as many chunks as you need, although at some point the find approach becomes easier than guess and check. – jw013 Apr 26 '12 at 14:24
  • upvoted for the for solution. Somehow I could not get to figure out how to use find -regex to match my files and your solution works just fine! – Adrien Nov 02 '21 at 14:13
14

Although jw013's answer is correct w.r.t globbing, that command may fail if you have thousands of matches: the expanded command line rm sequence_1_0001.hmf sequence_1_0002.hmf ... generated by the shell may simply be too big.

As Dom suggested, you can also use the -delete option with find:

find . -maxdepth 1 -type f -name 'sequence_1*.hmf' -delete

Both -maxdepth and -delete, while not in the POSIX standard are fairly common in find implementations in the wild. Linux distributions generally use GNU find, which certainly supports those options.

jw013
  • 51,212
Useless
  • 4,800
  • 2
    If you can, use the -delete option for find, it doesn't fork for each file... – Dom Apr 26 '12 at 14:08
  • Added, cheers. Looks like -delete should be supported on recent GNU and BSD systems, while -print0 is GNU-only. So it's likely more portable too (although it shouldn't make a difference for the OP). – Useless Apr 26 '12 at 15:13
  • At least OS X's find has -print0, but it's not included in POSIX. – Lri Apr 03 '13 at 20:26
5
rm sequence_1_{0000..0999}.hmf
rm sequence_1_{1000..1999}.hmf
rm sequence_1_{2000..2999}.hmf
...

would work too in Bash.

user unknown
  • 10,482
  • The brace expansion requires bash, and the zero padded form needs version 4, I believe. – jw013 Apr 26 '12 at 23:45