Your question is very hard to understand. In particular, you need to copy-paste your code and copy-paste error messages.
That being said, there's a good chance that you made a classic mistake…
When a shell script contains a variable substitution (something like $file
or $1
), the result of the expansion is treated as a whitespace-separated sequence of wildcard patterns. The variable is not treated as a single word, but as a list of patterns. So if you write
mv $1 /tmp # <<<< BAD
and you run myscript "file _name.dat"
, then the mv
command receives three arguments: file
, _name.dat
and /tmp
. If you run myscript "*.dat"
, then all the .dat
files in the current directory are moved.
To avoid this, put the variable substitution between double quotes: mv "$1" /tmp
. If you do this, mv
always receives exactly two arguments: the first argument of the script, and /tmp
. It is extremely rare to need to treat variables' values as lists of wildcard patterns, so remember this simple rule:
Always put double quotes around variable substitutions: "$foo"
, "$1"
, etc. This also goes for command substitutions: "$(mycommand)"
Furthermore, in case the file name begins with a dash (-
), mv
would treat it as an option. To avoid this, pass --
to mark the end of the options: anything after --
is a non-option argument (a file or directory name, for mv
). Most commands recognize --
to mark the end of options.
mv -- "$1" /tmp
If you wanted to invoke your script by writing myscript file _name.dat /tmp
in a shell, that is not possible. The script receives the arguments separately, it doesn't know how many spaces you happened to type on the command line. (This is different from Windows, where a program parses its own arguments. On unix, programs receive a list of arguments.) If you call your script from another shell script, use proper quoting in the calling script as well.
mv file _name.dat /tmp
and have it executemv "file _name.dat" /tmp
instead? – lk- Aug 16 '12 at 17:09