Скрипт Bash, который вызывает программу с некоторыми звездочками в аргументах

Скрипт Bash, который вызывает программу с некоторыми звездочками в аргументах

Последний час или около того я потратил на то, чтобы написать довольно простой скрипт 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"

Связанный контент