Problem if parameter has space in it using loop

for cmdopts in $*;do
 case $cmdopts in 
     -mode) 
  mode="$2";shift 2
     ;;
     -server) 
  server="$2";shift 2
     ;;
     -Id) 
  Id="$2";shift 2
     ;; 
     -passwd) 
  passwd="$2";shift 2
     ;;
     -rmtDir) 
  rmtDir="$2";shift 2
     ;; 
     -lcDir) 
  lcDir="$2";shift 2
     ;; 
     -file) 
  file="$2";shift 2;;
 esac
    done

statements... using above parameters.

This works fine if i pass
rmtDir='test/abc'
when i pass rmtDir='test/ghi jkl'
It complains connot find 'test/ghi" as it is looking of test/ghi rather than "test/ghi jkl"
The problem comes with the space in the directory path.
How do i handle this.

Help is appreciated.

you can solve this problem easily :

only put "" for the files separated by space:

e.g:- /test/"gg hh"

in this case the system will saw one file named as "gg hh"
BR

:slight_smile:

I tried this it doesnt work.

The "test/ghi jkl" is the directory path where "ghi jkl is also a direcotry name.

Help is appreciated.

let me discuss this issue in more details:-

each parameter (in bash shell) is a quoted string, that is, the parameters are passed on intact, without 
interpretation or expansion. This means, among other things, that each parameter in the argument list
is seen as a separate word if not quoted so you have to quote the variable to prevent the separation from occurring.

so the solution for you problem will be as follows"-

rmtDir=/what/ever/path/test/"ghi jkl" .... in here "ghi jkl" is one word

to test it do (to expand the variable):

cat (or cd if it is a directory) "${rmtDir}"

is it clear now?

BR
for cmdopts in "$@";do
also for cmdopts in "$*";do will work for the reason I said in previous quote
which is using "" in a var is necessary if there is spaces in this variable.
BR

No, it will not work. It will lump all the arguments into a single parameter; not what the OP wants at all.

In contrast, "$@" expands to each argument as a separate parameter, keeping arguments containing spaces as distinct parameters.

See the difference with this script:


## NAME: xx.sh
echo  'Using $*:'
printf "%s\n" $* ""

echo  'Using "$*":'
printf "%s\n" "$*" ""

echo  'Using "$@":'
printf "%s\n" "$@" ""

And a sample run:

xx.sh qw er 'ty ui' op
Using $*:
qw
er
ty
ui
op

Using "$*":
qw er ty ui op

Using "$@":
qw
er
ty ui
op
Definitions : 
$* :
All of the positional parameters, seen as a single word
"$*" must be quoted.
$@ :
Same as $*, but each parameter is a quoted string, that is, the parameters are passed on intact, without
interpretation or expansion. This means, among other things, that each parameter in the argument list
is seen as a separate word.
Of course, "$@" should be quoted.





kindly see this exapmle where $*,$@ & "$@" act in same behaviour

e.g:-

#!/bin/bash
# If $IFS set, but empty,
#+ then "$*" and "$@" do not echo positional params as expected.
mecho () # Echo positional parameters.
{
echo "$1,$2,$3";
}
IFS="" # Set, but empty.
set a b c # Positional parameters.
mecho "$*" # abc,,
mecho $* # a,b,c
mecho $@ # a,b,c
mecho "$@" # a,b,c
# The behavior of $* and $@ when $IFS is empty depends
#+ on whatever Bash or sh version being run.
# It is therefore inadvisable to depend on this "feature" in a script.

conclusion :- 
1- The $@ and $* parameters differ only when between double quotes.
2- The $* and $@ parameters sometimes display inconsistent and puzzling behavior,
depending on the setting of $IFS.

Incorrect; wordsplitting is performed on $* (it is unquoted).

It must only be quoted if you want it as a single word; if you want it as more than one word it must not be quoted.

True.

That is not true. Each parameter is a separate parameter (not a quoted string) only if $@ is in quotes.

It should be quoted if you want each parameter to be regarded as such in the script.

It is much more reliable to use printf than echo if you really want to see exactly what the parameters are:

mecho() #@ Print each argument on a separate line.
{
 printf "%s\n" "$@" "" ## add a blank line after the parameters
}

You would have a much more meaningful demonstration if you had spaces in some of the parameters.

Expressed more concisely and precisely:

"$@" always expands to each of the positional parameters as a separate argument.

"$*" always expands to a single argument comprising all the positional parameters; how they are separated depends on the value of $IFS.

$* and $@ always expand each word (not each argument) on the command line as a separate argument.

Here are the definitions according to the POSIX shell specification.

@Expands to the positional parameters, starting from one. When the expansion occurs within double-quotes, and where field splitting (see Field Splitting ) is performed, each positional parameter shall expand as a separate field, with the provision that the expansion of the first parameter shall still be joined with the beginning part of the original word (assuming that the expanded parameter was embedded within a word), and the expansion of the last parameter shall still be joined with the last part of the original word. If there are no positional parameters, the expansion of '@' shall generate zero fields, even when '@' is double-quoted.

*Expands to the positional parameters, starting from one. When the expansion occurs within a double-quoted string (see Double-Quotes ), it shall expand to a single field with the value of each parameter separated by the first character of the IFS variable, or by a <space> if IFS is unset. If IFS is set to a null string, this is not equivalent to unsetting it; its first character does not exist, so the parameter values are concatenated.

I just want to say that :- $* , $@ & "$@" will work in the same behavior if "Input Field Seperator " IFS = ""
in conclusion:- code posted in the first place is true only if IFS="" .....

you can see this result if you test the bellow example and see the difference when changing the IFS from " " to ":" to "".
BR

Example:-



set -- "First one" "second" "third:one" "" "Fifth: :one"
# Setting the script arguments, $1, $2, etc.
echo
echo 'IFS unchanged, using "$*"'
c=0
for i in "$*" # quoted
do echo "$((c+=1)): [$i]" # This line remains the same in every instance.
# Echo args.
done
echo ---
echo 'IFS unchanged, using $*'
c=0
for i in $* # unquoted
do echo "$((c+=1)): [$i]"
done
echo ---
echo 'IFS unchanged, using "$@"'
c=0
for i in "$@"
do echo "$((c+=1)): [$i]"
done
echo ---
echo 'IFS unchanged, using $@'
c=0
for i in $@
do echo "$((c+=1)): [$i]"
done
echo ---
IFS=:
echo 'IFS=":", using "$*"'
c=0
for i in "$*"
do echo "$((c+=1)): [$i]"
done

echo 'IFS=":", using $*'
c=0
for i in $*
do echo "$((c+=1)): [$i]"
done
echo ---
var=$*
echo 'IFS=":", using "$var" (var=$*)'
c=0
for i in "$var"
do echo "$((c+=1)): [$i]"
done
echo ---
echo 'IFS=":", using $var (var=$*)'
c=0
for i in $var
do echo "$((c+=1)): [$i]"
done
echo ---
var="$*"
echo 'IFS=":", using $var (var="$*")'
c=0
for i in $var
do echo "$((c+=1)): [$i]"
done
echo ---
echo 'IFS=":", using "$var" (var="$*")'
c=0
for i in "$var"
do echo "$((c+=1)): [$i]"
done
echo ---
echo 'IFS=":", using "$@"'
c=0
for i in "$@"
do echo "$((c+=1)): [$i]"
done
echo ---
echo 'IFS=":", using $@'
c=0
for i in $@
do echo "$((c+=1)): [$i]"
done
echo ---
var=$@
echo 'IFS=":", using $var (var=$@)'
c=0
for i in $var
do echo "$((c+=1)): [$i]"
done
echo ---
echo 'IFS=":", using "$var" (var=$@)'

c=0
for i in "$var"
do echo "$((c+=1)): [$i]"
done
echo ---
var="$@"
echo 'IFS=":", using "$var" (var="$@")'
c=0
for i in "$var"
do echo "$((c+=1)): [$i]"
done
echo ---
echo 'IFS=":", using $var (var="$@")'
c=0
for i in $var
do echo "$((c+=1)): [$i]"
done
echo
# Try this script with ksh or zsh -y.
exit 0