I have a simple bash script:

input_dir="`dirname $1`/`basename $1`/"
output_dir="`dirname $2`/`basename $2`/"
echo -n `rename "-f" "'s/.*([0-9]{11}_[0-9]{11}).*\.(.*$)/$1.$2/'" "$output_dir"*.$ext`

The problem is that it does not work because the match groups $N conflict with command line arguments to the script. How can I solve this?

2 Answers 2


Regarding the question you asked: use single quotes around a literal string where you don't want any substitution to happen. If you need a single quote in that string, type it as '\''.

echo -n `rename "-f" 's/.*([0-9]{11}_[0-9]{11}).*\.(.*$)/$1.$2/' "$output_dir"*.$ext`

There's something else wrong with your code. The result of a variable susbtitution like $1 and $2 or a command substitution like `rename …` is parsed by the shell, it performs word splitting and globbing on the result. Always use double quotes around variable substitutions and command substitutions unless you know you need to omit them. Furthermore, don't use backquotes, as they handle nested quotes in tricky and shell-dependent ways. All shells outside museums support the saner $(…) syntax. Also you need a -- on the invocations of dirname and basename, in case $1 or $2 starts with a - and thus looks like an option.

input_dir="$(dirname -- "$1")/$(basename -- "$1")/"
output_dir="$(dirname -- "$2")/$(basename -- "$2"/)"
ext="$3"    # here it would be ok to omit the quotes, but if you're unsure of the rules, put the quotes in
echo -n "$(rename -f 's/.*([0-9]{11}_[0-9]{11}).*\.(.*)$/$1.$2/' "$output_dir"*".$ext")"

As an aside, I don't understand what you're trying to achieve here. The way you're invoking it, rename doesn't produce any output.


In general, you can stop the shell from interpreting a metacharacter by escaping it with a backslash (\). So, you can prevent all the $ in the rename argument from being expanded by prepending a backslash:

echo -n `rename "-f" "'s/.*([0-9]{11}_[0-9]{11}).*\.(.*\$)/\$1.\$2/'" "$output_dir"*.$ext`

In this particular case, since the string s/.*([0-9]...$2/ does not need any shell-level substitutions (the whole point of your question is how to prevent them), you could just enclose it in single quotes (') which prevents all shell processing:

echo -n `rename "-f" 's/.*([0-9]{11}_[0-9]{11}).*\.(.*$)/$1.$2/' "$output_dir"*.$ext`

(Note that you do not need quotes around the -f, since it does not contain any shell metacharacters.)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .