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

1103
kirelagin

Я провел последний час или около того, пытаясь написать довольно простой сценарий 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 */*.

PS На самом деле первая строка немного сложнее 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 '*/*'(одинарные кавычки не должно быть там).

Кажется, что я пробовал каждую комбинацию кавычек и обратной косой черты звездочек, и я буквально не знаю, что теперь делать.

0

2 ответа на вопрос

0
AFH

Я использовал ваш оригинальный скрипт, но с одинарными кавычками в первой строке (только), и он работал так, как я думаю, вы хотите ( -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\" " 
Нет, это все равно выполняет расширение в цикле `for` и выводит` a / b` вместо `* / *`. Другая проблема заключается в том, что первая строка несколько сложнее в реальности; Я обновлю вопрос через минуту. kirelagin 9 лет назад 0
Я думал, что вы хотите, чтобы это расширилось в цикле `for`. Я протестировал его на Ubuntu 14.04 и получил `-0" foo / bar "-0" dir / file "-0" dir / file "...` AFH 9 лет назад 0
Возможно, вы захотите прочитать мой вопрос еще раз, особенно ту часть, которая находится прямо перед горизонтальной линейкой, которая дает желаемый результат: расширение _no_ должно быть выполнено; Мне нужно, чтобы все звездочки остались на месте. kirelagin 9 лет назад 0
ХОРОШО. Я нашел то, что работает. Создайте первую строку `xs =" foo / bar @ / @ "`, затем после цикла `for` добавьте строку` xs_cmd = $ (echo $ xs_cmd | sed "s / @ / \ * / g") `. Если вы не можете найти такой символ, как `@`, которого нет ни в одном из имен файлов, используйте `xs =" foo / bar /// "` и `xs_cmd = $ (echo $ xs_cmd | sed" s - /// - \ * / \ * - г ")`. Сначала я предложил использовать `@`, так как для других строк проще сделать звездочки. AFH 9 лет назад 0
Итак, теперь у меня есть `xs_cmd`, который представляет собой строку с некоторыми звездочками. Как передать это команде (`echo` в моем примере)? `echo $ xs_cmd` выполнит расширение. `echo" $ xs_cmd "` вызовет `echo` с одним аргументом. kirelagin 9 лет назад 0
Я имею в виду, что программирование оболочки действительно безумно. Я мог бы написать эту программу на любом другом языке за две минуты и заставить ее работать всего за одну попытку. Но теперь я действительно хочу знать, как написать это в оболочке! kirelagin 9 лет назад 0
Поскольку вы боретесь с расширением имени файла, почему бы не отключить его в этом контексте с помощью `set -f` и впоследствии восстановить его с помощью` set + f`? AFH 9 лет назад 0
Ах, конечно! Ну, я бы классифицировал это как обходной путь, а не как истинное решение (потому что мне все еще интересно, как это сделать напрямую), но это работает. Спасибо! kirelagin 9 лет назад 0
Я думал о вашем комментарии, и я не считаю, что это обходной путь. Ваш сценарий не выполняется, потому что звездочки расширяются, когда вы этого не хотите, поэтому остановка их расширения в неподходящее время является решением, потому что это именно то, что пытаются сделать другие предложения. AFH 9 лет назад 0
0
oxij

Depending on what you're trying to achieve, your either need to quote these */*:

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" 

or use arrays, or both:

xs=("foo/bar" "*/*") #! xs_cmd="" for x in "$"; do xs_cmd="$xs_cmd -0 '$x' " #! done echo "$xs_cmd" eval "echo $xs_cmd" 
Как упоминалось в моем вопросе, ваше первое предложение приводит к следующему выводу: `-0 foo / bar -0 '* / *'`, что означает, что кавычки буквально передаются программе. Ваше второе предложение приводит к `-0 'foo / bar' -0 'a / b'`, который _both_ передает кавычки в программу ** и ** выполняет расширение, в то время как мне не нужно ни того, ни другого. kirelagin 9 лет назад 0

Похожие вопросы