Aggiungi argomenti a 'bash -c'


22

Diciamo che voglio eseguire un comando tramite Bash in questo modo:

/bin/bash -c "ls -l"

Secondo la pagina man di Bash, potrei anche eseguirlo in questo modo:

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

tranne che non sembra funzionare (sembra ignorato). Sto facendo qualcosa di sbagliato o sto interpretando la pagina man sbagliata?

Citazioni rilevanti dall'uomo:

Se l'opzione -c è presente, i comandi vengono letti dalla stringa. Se ci sono argomenti dopo la stringa, vengono assegnati ai parametri posizionali, a partire da $ 0.

e

A - segnala la fine delle opzioni e disabilita l'ulteriore elaborazione delle opzioni. Eventuali argomenti dopo il - sono trattati come nomi di file e argomenti.

Risposte:


33

Stai interpretando la pagina man in modo errato. In primo luogo, la parte relativa alla --segnalazione della fine delle opzioni è irrilevante rispetto a ciò che stai cercando di fare. Gli -coverride il resto della linea di comando da quel momento in poi, in modo che non è più in corso è attraverso la gestione delle opzioni di bash a tutti, il che significa che la --sarebbero passati attraverso il comando, non gestite da bash come un fine di marcatore opzioni.

Il secondo errore è che argomenti aggiuntivi vengono assegnati come parametri posizionali al processo della shell avviato, non passati come argomenti al comando. Quindi, quello che stai cercando di fare potrebbe essere fatto come uno di:

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

Nel primo caso, passando echo i parametri $0ed $1esplicitamente, e nel secondo caso, usando "$@"per espandere normalmente come "tutti i parametri posizionali tranne $ 0". Si noti che in quel caso dobbiamo passare anche qualcosa da usare $0; Ho scelto "bash" poiché è quello che $0sarebbe normalmente, ma qualsiasi altra cosa funzionerebbe.

Per quanto riguarda il motivo è fatto in questo modo, invece di passare tutti gli argomenti si danno direttamente al comando vi elenco: nota che la documentazione dice "comando s vengono letti dalla stringa", plurale. In altre parole, questo schema ti consente di fare:

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

Tuttavia, tieni presente che un modo migliore per raggiungere il tuo obiettivo originale potrebbe essere quello di utilizzare envpiuttosto che bash:

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

Se non hai bisogno di nessuna delle funzionalità fornite da una shell, non c'è motivo di usarla - l'utilizzo envin questo caso sarà più veloce, più semplice e meno digitazione. E non devi pensarci tanto per essere sicuro che gestirà in modo sicuro nomi di file contenenti metacaratteri di shell o spazi bianchi.


3

Non sono sicuro di quale sia il tuo obiettivo, ma se stai semplicemente cercando di costruire una macchina Rube Goldberg - “un aggeggio, un'invenzione, un dispositivo o un apparato deliberatamente sovra ingegnerizzato o esagerato per eseguire un compito molto semplice in un moda complicata ”- quindi prova

sh -c 'ls $0' -l

o

sh -c 'ls $1' supercalifragilisticexpialidocious -l

o anche

sh -c 'ls -$0' l

Dovresti essere in grado di capire come funzionano dalla risposta di godlygeek.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.