1

I want to rename a file dynamically based on data which contains spaces

Name="Abc DEF"
Name1="GHI JKL"

mv /sample/pdf/noriginalName.pdf /sample/outputPdf/${NAME}${Name1}".pdf"

But it gives me an error because it encounters space in between.

How can I do this?

Rahul
  • 11

2 Answers2

5

Don't worry, you're not the first and won't be the last one to be bitten by that. It's the most frequently asked question about shells, and that's responsible for most bugs and security vulnerabilities found in shell scripts. That's due to a bad design choice of the Bourne shell and the Korn shell in the earlier Unix history.

In the Bourne shell and most of its descendants (ksh, ash, pdksh, mksh, bash, dash, yash...), leaving a variable unquoted is the split+glob operator.

Best demonstrated with:

$ var='*.txt,.*'
$ IFS=',' # default is space tab and newline
$ printf '<%s>\n' $var
<file.txt>
<.>
<..>

The shell has split $var on , characters and expanded each of the resulting words (which in this case contain wildcard characters) in the list of files matching the corresponding pattern.

That's why, in Bourne-like shells (except zsh), you must always quote your variables (unless you do want the split and/or glob)

$ printf '<%s>\n' "$var"
<*.txt:.*>

So in your case:

mv /sample/pdf/noriginalName.pdf "/sample/outputPdf/${NAME}${Name1}.pdf"

or:

mv /sample/pdf/noriginalName.pdf /sample/outputPdf/"${NAME}${Name1}".pdf

(where you put the quotes doesn't matter as long as the variables are quoted).

You can disable the splitting only with:

IFS=

And you can disable the globbing only with:

set -f # affects all globbing, not only the one done upon variable expansion.

With:

IFS=; set -f

You get the same behaviour as zsh for parameter expansion, no globbing, no splitting. You still need to quote your variable however in

cmd "$var"

If you want cmd to be passed one empty argument when $var is empty or unset (as opposed to no argument at all). A typical example is [ -n "$var" ] where if you don't quote $var, the test will alway be true since when $var is empty, that resolves to [ -n ] instead of [ -n '' ].

In zsh, globbing and splitting is not done implicitly upon variable expansion (except in sh or ksh emulation mode). You have to request it explicitly using specific expansion operators: $=var for word splitting, $~var for globbing (or ${~var}; $~=var for both).

The other shells that don't have this kind of problem are fish, and rc and its descendants (es, akanga).

In (t)csh:

cmd "$var"

helps but is not enough, as it doesn't work if $var contains newline characters. There, you need:

cmd $var:q
4

You must quote the whole file name:

mv /sample/pdf/noriginalName.pdf "/sample/outputPdf/${NAME}${Name1}.pdf"

Using double quote prevent bash and other Bourne-like shells (except zsh) perform Field splitting after your variable is expanded.

cuonglm
  • 153,898