This question already has an answer here:

I want to to remove all color codes which look like '@n', '@R' etc, from a moderately large size collection of text files.

So in a file called 'remove_cc', I wrote the following:

sed -ie 's/@r//g' $1
sed -ie 's/@g//g' $1
sed -ie 's/@y//g' $1
sed -ie 's/@b//g' $1
sed -ie 's/@m//g' $1
sed -ie 's/@c//g' $1
sed -ie 's/@n//g' $1
sed -ie 's/@R//g' $1
sed -ie 's/@G//g' $1
sed -ie 's/@Y//g' $1
sed -ie 's/@B//g' $1
sed -ie 's/@M//g' $1
sed -ie 's/@C//g' $1
sed -ie 's/@N//g' $1
sed -ie 's/@W//g' $1
sed -ie 's/@K//g' $1

Anyways, the script works fantastically if I use it like: ./remove_cc file.txt

But if I type ./remove_cc *.txt in a folder with many txt files that I want to run the script on, it fails to do anything. ./remove_cc * is equally ineffective.

Is there a way to fix this so it works?

marked as duplicate by jasonwryan, peterph, slm Oct 7 '14 at 1:43

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • Just a short note: -i is not specified by POSIX, so you may encounter seds that won't understand it. – peterph Oct 6 '14 at 19:03

When you type ./remove_cc *, the shell changes it to ./remove_cc file1.txt file2.txt file3.txt etc, and runs your script that way. Your script is only looking at $1, the first parameter (file1.txt).

The most general way to do this is to loop over each parameter in turn. "$@" expands to the list of all the parameters, and we can use for to loop over them.

for n in "$@" ; do
    sed -ie 's/@r//g' "$n"

In this particular case, since sed will take multiple filenames, you can simplify:

sed -ie 's/@r//g' "$@"

Note that paying attention to quotes is important when writing shell scripts. Without the quotes, for example, the script would not work on a file named My Text File.txt.


just use

 for x in *
     ./remove_cc $x

By the way, you can combine all sed in one line

sed -i \
    -e 's/@r//g' -e 's/@g//g' -e 's/@y//g' -e 's/@b//g' \
    -e 's/@m//g' -e 's/@c//g' -e 's/@n//g' -e 's/@R//g' \
    -e 's/@G//g' -e 's/@Y//g' -e 's/@B//g' -e 's/@M//g' \
    -e 's/@C//g' -e 's/@N//g' -e 's/@W//g' -e 's/@K//g' \

you can also join sed commands with semicolons:

sed -i -e 's/@r//g;s/@g//g;s/@y//g' $1

or just use character list

sed -i -e s/@[rgbcmyRGBCMY]//g $1


 sed -i -e s/@[rgbcmyRGBCMY]//g *

(be sure to check I have put all the letter)


Use "$@" instead of $1. Or quote the wildcard:

$ bash -c 'echo $1' 'some command' '*'
file1 file2
$ bash -c 'echo "$@"' 'some command' *
file1 file2

If you do not wish to change your script you can also use xargs (considering you have it or it's available on your platform) by running it like this:

ls *.txt | xargs -L1 ./remove_cc

xargs is a utility that takes stdin and transforms it to command parameters on a command to be run. It has the -L flag that limits the amount of input lines to be used in a single execution.

Not the answer you're looking for? Browse other questions tagged or ask your own question.