23

Suppose I have a bunch of files named this way:

file01.txt file02.txt file03.txt ... file20.txt

and I want to execute a command on a range of these files.

I know if want to 'rm' from 'file05.txt' to 'file09.txt' I can do:

rm file0[5-9].txt

but how can I 'rm' a range from file08.txt to file13.txt? I tried this code

rm file[08-13].txt

and it doesn't work. I could run this command:

rm file0[89].txt file1[0-3].txt

but I'd like to know if I can do this with only one more refined argument to 'rm' if it is possible.

40

You need to use brace expansion of bash:

rm file{08..13}.txt

This will remove files file08 to file13, will show an error message if any file is missing.

Set the range to meet your need.


The problem with the globbing operator [] is that it treats each character/digit inside it as a single token and so only supports range declaration using single digits.

If you insist on using [], you can use this rather ugly pattern to match file08 to file13:

rm file0[8-9].txt file1[0-3].txt
| improve this answer | |
  • 5
    brace expansion is also useful with commas, like for mv foo.{txt,md} or cp foo.txt{,.bak} – Kos Aug 7 '16 at 19:42
2

Some shells, such as Ubuntu's default /bin/sh ( which is dash ) or mksh don't have brace expansion, or in case of ksh - brace expansion can't use padded zeroes :

$ ksh -c 'echo {05..13}'
5 6 7 8 9 10 11 12 13

In such cases, we can make use of printf to format the number portion of the filename, and use a while loop to implement c-like for loop behavior (note to replace echo with rm or whatever you want):

$ i=5; while [ "$i" -le 10 ]; do num=$(printf "%.2d" "$i" ); echo "file$num.txt";i=$(($i+1)); done
file05.txt
file06.txt
file07.txt
file08.txt
file09.txt
file10.txt

And this is fairly portable - works with dash, ksh, mksh, also bash. In the case of ksh and bash we can also use c-style for loop syntax (but not in case ofmkshordash`):

$ ksh -c 'for((i=5;i<11;i++)); do num=$(printf "%.2d" "$i" ); echo "file$num.txt";done'             
file05.txt
file06.txt
file07.txt
file08.txt
file09.txt
file10.txt

Note that in bash's case, printf supports printing to variable, and thus we could do printf -v num "%.2d" "$i" instead of using command substitution.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy