I have number of files with similar names suffixed with number from 1 to 500. I want to delete the files from 1 to 250 only. is there a way to do that using wildcard.

files are: stdout.1 to stdout.500

I want to delete files from stdout.1 to stdout.250.


  • Why not just rm stdout.{1..250}
    – Inian
    Jun 22 '20 at 7:46
  • Hi Inian, Thanks for this. I wasn't aware curly braces can be used for range. Its working. But few files are missing between 1 to 250 which shows the "No file or directory" error. is there any way to execute only if its present. Just like it is performed with [0-9] when we use range in wildcard using [].
    – Navi
    Jun 22 '20 at 7:53
  • just add -f; gets rid of the message as well as ignores the missing files in setting the exit code.
    – user339730
    Jun 23 '20 at 0:47

In Zsh, you could do just rm stdout.<1-250>. <n-m> matches parts of the filename that represent a decimal integer number from n to m. (Possibly with leading zeroes, so stdout.0099 would also match.)

In Bash, you could use brace expansion: rm stdout.{1..250}. Though the difference with Zsh's <1-250> is that brace expansion generates strings without regard for existing files, so you may get errors if a file is missing from the middle of the list. In the case of rm, adding the -f option would silence those errors as with -f, rm only complains if any file you ask it to unlink would still be there after it returns.

If you want to avoid generating names of non-existing files, or are limited to standard sh (i.e. without brace expansion), then you'll have to do the matching character by character. So:

rm stdout.? stdout.??       #   1 to  99
rm stdout.1??               # 100 to 199
rm stdout.2[01234]?         # 200 to 249
rm stdout.250               # 250

However note that if there's no file that matches rm stdout.2[01234]?, that would end up removing a file called stdout.2[1234]? if it existed.

  • What's the difference between zsh's <1-150> and the bash's {1..150}? Does it only expand to the existing file names?
    – terdon
    Jun 22 '20 at 8:27
  • @terdon, zsh's <1-150> is a glob, so it only matches existing filenames. Also it seems to match leading zeroes, so 1 and 0001 both fit. Brace expansion just produces strings, they don't need to have matching existing files.
    – ilkkachu
    Jun 22 '20 at 13:51
  • Note that {1..250} also comes from zsh (added in 1995). bash copied it (a subset initially) in 2004, ksh93 in 2005, yash in 2008. There are some variations between all 4 implementations, but they should all work the same for the simple case of rm stdout.{1..250} Jun 22 '20 at 14:09

You can use brace expansion for this

rm stdout.{1..500}

That command will be expanded to rm stdout.1 stdout.2 ... stdout.500. If some of the files don't exist, you will get an error message, but you can safely ignore that. Alternatively, you can redirect stderr so you don't see it:

rm stdout.{1..500} 2>/dev/null

Or, but this will be considerably slower, you can loop over the files and run rm on those that exist only:

for f in stdout.{1..500}; do
    [ -e "$f" ] && rm "$f"

You can also just delete all files whose name starts with stdout. and ends in one or more numbers:

rm stdout.[0-9]*

But that only works if you don't have files that match the pattern which you want to keep, since it will delete all files show name starts with stdout. followed by any number, so it will also delete files like stdout.501 which aren't part of your range.

  • Hi terdon, I think it might be valuable to stress out that the last form, rm stdout.[0-9]*, would also remove stdout.5X, for example.
    – Quasímodo
    Jun 22 '20 at 11:38
  • @Quasímodo fair enough. Done, thanks.
    – terdon
    Jun 22 '20 at 12:01
  • 2
    You're welcome. But stdout.4 is part of his range, not? :)
    – Quasímodo
    Jun 22 '20 at 15:25
  • @Quasímodo lol, I guess I should re-read the question before editing my answer! Thanks again :)
    – terdon
    Jun 22 '20 at 21:24
  • no need to redirect stderr or loop through each filename checking if it exists; just add -f to the rm command
    – user339730
    Jun 23 '20 at 0:49

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.