Додати аргументи до 'bash -c'


22

Скажімо, що я хочу запустити команду через Bash так:

/bin/bash -c "ls -l"

Як повідомляє сторінка Man Bash, я також міг би це запустити так:

#               don't process arguments after this one
#               |   pass all unprocessed arguments to command
#               |   |
#               V   V
/bin/bash -c ls -- -l

за винятком того, що він не працює (здається, ігнорується). Чи я щось роблю не так, чи неправильно трактую сторінку людини?

Відповідні цитати від людини:

Якщо параметр -c присутній, то команди зчитуються з рядка. Якщо після рядка є аргументи, вони присвоюються позиційним параметрам, починаючи з $ 0.

і

А - сигналізує про закінчення параметрів і вимикає подальшу обробку опцій. Будь-які аргументи після - трактуються як імена та аргументи.

Відповіді:


33

Ви неправильно трактуєте сторінку чоловіка. По-перше, частина про --сигналізацію про закінчення параметрів не має значення для того, що ви намагаєтесь зробити. З цього -cмоменту переорієнтовує решту командного рядка, так що він більше не проходить через керування опціями bash, це означає, що --перехід буде переданий команді, а не обробляється bash як кінець маркера параметрів.

Друга помилка полягає в тому, що додаткові аргументи призначаються як позиційні параметри запущеного процесу оболонки, а не передаються як аргументи команді. Отже, те, що ви намагаєтесь зробити, можна зробити як один із:

/bin/bash -c 'echo "$0" "$1"' foo bar
/bin/bash -c 'echo "$@"' bash foo bar

У першому випадку, передаючи параметри ехо $0і $1явно, а в другому випадку, використовуючи "$@"для розширення настільки ж нормально, як "всі позиційні параметри, крім $ 0". Зауважте, що і в цьому випадку ми повинні передавати те, що також буде використано $0; Я вибрав "баш", оскільки це $0зазвичай було б, але все інше спрацювало б.

Що стосується причини, яка робиться таким чином, замість того, щоб просто передавати будь-які аргументи, які ви даєте безпосередньо команді, яку ви перераховуєте: зауважте, що в документації написано "команда s читається з рядка", множина. Іншими словами, ця схема дозволяє робити:

/bin/bash -c 'mkdir "$1"; cd "$1"; touch "$2"' bash dir file

Але зауважте, що кращим способом досягнення первинної мети може бути використання, envа не bash:

/usr/bin/env -- "ls" "-l"

Якщо вам не потрібна якась функція, яку надає оболонка, немає ніяких причин використовувати її - використання envв цьому випадку буде швидшим, простішим та меншим набором тексту. І вам не потрібно думати так важко, щоб переконатися, що він буде безпечно обробляти імена файлів, що містять метахарактеристики оболонки або пробіли.


3

Я не впевнений, у чому полягає ваша мета, але якщо ви просто намагаєтеся створити машину Руба Гольдберга - «контрацепція, винахід, пристрій або апарат, який навмисно перероблений або перероблений для виконання дуже простого завдання в дуже складна мода »- тоді спробуйте

sh -c 'ls $0' -l

або

sh -c 'ls $1' supercalifragilisticexpialidocious -l

або навіть

sh -c 'ls -$0' l

Ви повинні мати можливість зрозуміти, як це працює з відповіді godlygeek.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.