Bash - be safe when saving $@ in a variable

I am having a problem navigating through such a variable. I prepared 2 examples to show the problem.

EX1:

#!/bin/bash DIRS=" $@ " for DIR in $DIRS; do echo "$DIR" done 

ex2:

 #!/bin/bash for DIR in " $@ "; do echo "$DIR" done 

The second example works as expected (and required). The following is a quick test:

 $ ex1 "ab" "c" a b c $ ex2 "ab" "c" ab c 

The reason I want to use the first method is because I want to be able to pass multiple directories to the program or not, in order to use the current directory. For example:

 [ $# -eq 0 ] && DIRS=`pwd` || DIRS=" $@ " 

So how can I get example 1 for security?

+7
source share
3 answers

Use an array instead of a simple variable.

 declare -a DIRS DIRS=(" $@ ") for d in "${DIRS[@]}" do echo "$d" done 

This leads to the result:

 $ bash xx.sh a "bc" "defg" hz a bc defg h z $ 
+10
source

Why not use the default extension feature?

 for DIR in "${@:-$(pwd)}"; do echo $DIR done 
+4
source

One approach is to replace the spaces inside the arguments with something else, and then replace the spaces again when using the argument:

 dirs="${@/ /###}" for dir in $dirs; do echo "${dir/###/ }" done 

It depends on whether you can come up with some sequence of characters that you can be sure will never appear in the real file name.

For a specific situation, when you want to be able to choose between providing an explicit list of directories or the default for the current directory, the best solution is probably to use the function:

 do_something() { for dir in " $@ "; do echo "$dir" done } if [ $# -eq 0 ]; then do_something . else do_something " $@ " fi 

Or perhaps:

 do_something() { echo "$1" } if [ $# -eq 0 ]; then do_something . else for dir in " $@ "; do do_something "$dir" done fi 
0
source

All Articles