Последний час или около того я потратил на то, чтобы написать довольно простой скрипт bash, и никогда не чувствовал себя таким идиотом.
Итак, у меня есть список строк (которые являются спецификациями селектора пакетов для менеджера пакетов, если это имеет значение), которые могут содержать звездочки. Мне нужно создать командную строку, сохраняющую эти звездочки, а затем вызвать программу. Вот моя наивная попытка:
xs="foo/bar */*"
xs_cmd=""
for x in $xs; do
xs_cmd="$xs_cmd -0 $x "
done
echo $xs_cmd
Мне нужно, echo
чтобы вызов был эквивалентен
echo -0 foo/bar -0 '*/*'
который выводит -0 foo/bar -0 */*
.
P.S. На самом деле первая строка немного сложнее: xs="$some foo/bar */* $(get_others)"
.
Если вы запустите этот скрипт в каталоге, содержащем a/b
, вы получите -0 foo/bar -0 a/b
вместо этого.
Когда я меняю последнюю строку на
echo "$xs_cmd" # note the quotes
Я получаю -0 foo/bar -0 a/b
, и, во-первых, это не то, чего я хочу, так как теперь я вызываю echo
с помощьюодинокийаргумент, и, более того, это говорит мне о том, что расширение происходит раньше, вероятно, в for
цикле.
Но я не могу изменить строку, for
потому что
for x in "$xs"; do # note the quotes
просто заставит цикл повториться только один раз: -0 foo/bar */*
(есть один -0
), поэтому добавление этих кавычек — это точно не вариант.
Теперь, если я вернусь к исходному сценарию и заменю первую строку на
xs="foo/bar '*/*'" # note additional single quotes
Я понимаю -0 foo/bar -0 '*/*'
(одинарных кавычек быть не должно).
Кажется, я перепробовал все комбинации кавычек и экранирования звездочек обратным слешем, и теперь понятия не имею, что делать дальше.
решение1
Я использовал ваш оригинальный скрипт, но с одинарными кавычками в первой строке (только) и он сработал так, как, я думаю, вы и хотели ( -0
перед каждым путем к файлу):-
xs='foo/bar */*'
xs_cmd=""
for x in $xs; do
xs_cmd="$xs_cmd -0 $x "
done
echo $xs_cmd
Вы, вероятно, столкнетесь с проблемами, когда начнете его использовать, если в пути к файлу есть встроенные пробелы. Если это так, измените команду в цикле на:-
xs_cmd="$xs_cmd -0 \"$x\" "
решение2
В зависимости от того, чего вы пытаетесь добиться, вам нужно будет процитировать следующее */*
:
xs="foo/bar '*/*'" #!
xs_cmd=""
for x in $xs ; do
xs_cmd="$xs_cmd -0 $x "
done
echo $xs_cmd
eval echo $xs_cmd
eval "echo $xs_cmd"
или используйте массивы, или и то, и другое:
xs=("foo/bar" "*/*") #!
xs_cmd=""
for x in "${xs[@]}"; do
xs_cmd="$xs_cmd -0 '$x' " #!
done
echo "$xs_cmd"
eval "echo $xs_cmd"