问题
I have the following Bash script:
DIR="~/Folder/With\ Spaces"
CMD="find $DIR -type f"
# echo showing hidden characters
echo $CMD | cat -v
while read line
do
echo $line
done < <($CMD)
The output:
find ~/Folder/With\ Spaces -type f
find: ~/Folder/With\: No such file or directory
find: Spaces: No such file or directory
I've gone through this every way I can think of, with single and double quotes, backslash and no backslash, quotes around the variable in the other lines, no dice.
If I understand this correctly, CMD should be the following:
find ~/Folder/With\ Spaces -type f
This should work fine, and since find
can't use quotes around its path, this is the correct way to do it. The echo shows it matches this. Typing this string into the command line works fine. Again, the echo
command prints this. But the output of the script says there's something else going on, probably on the done
line where the command is being executed.
How would I get Bash to interpret the filename as one path in this context? And why? The backslash (to stop it from interpreting it as two parts separated by spaces) is being treated as part of the string, so where is it splitting it, and why?
回答1:
Bash never evaluates data as code, but it does some things that could make you think it does (namely word splitting and globbing). Since \
is part of shell syntax, it's not reinterpretted as an escape sequence when you expand the variable.
Here's how you should do it:
DIR=~/"Folder/With Spaces" # ~ doesn't expand in quotes, and there's no "\".
CMD=(find "$DIR" -type f) # use an array to keep track of words
# Print the words escaped so you know what will actually be executed
printf "%q " "${CMD[@]}" | cat -v
echo
while IFS= read -r line # don't split or interpret words
do
echo "$line" # use quotes to prevent globbing and word splitting
done < <("${CMD[@]}") # run the command in the array without spacing issues
来源:https://stackoverflow.com/questions/21395836/bash-script-quote-issues