2014-01-28 4 views
1

У меня есть следующий Bash скрипт:Bash цитата скрипт выдает

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) 

Выход:

find ~/Folder/With\ Spaces -type f 
find: ~/Folder/With\: No such file or directory 
find: Spaces: No such file or directory 

Я прошел через это все так, как я могу думать, с одинарными и двойными кавычками, обратная косая черта и отсутствие обратной косой черты, цитаты вокруг переменной в других строках, без костей.

Если я понимаю, это правильно, CMD должны быть следующие:

find ~/Folder/With\ Spaces -type f 

Это должно работать нормально, и так find не может использовать кавычки пути, это правильный способ сделать это. Эхо показывает, что оно соответствует этому. Ввод этой строки в командную строку прекрасен. Опять же, команда echo печатает это. Но вывод скрипта говорит, что происходит что-то еще, возможно, на линии done, где выполняется команда.

Как я могу заставить Bash интерпретировать имя файла как один путь в этом контексте? И почему? Обратная косая черта (чтобы остановить ее от интерпретации ее как двух частей, разделенных пробелами) рассматривается как часть строки, поэтому, где она разбивает ее и почему?

ответ

5

Bash никогда не оценивает данные как код, но он делает некоторые вещи, которые могут заставить вас думать, что это так (а именно разбиение слов и глобус). Поскольку \ является частью синтаксиса оболочки, он не переинтерпретируется как escape-последовательность при расширении переменной.

Вот как вы должны это сделать:

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 
+0

Три вещи. 1: это работает. 2: Ты гений. 3: «Правильное» решение убедило меня переключиться на Python. : D –

+0

Чем глубже я вникаю в bash, тем веселее я с людьми, говорящими, что Perl выглядит как линейный шум. –

Смежные вопросы