Mi chiedo se esiste un modo generale per passare più opzioni a un eseguibile tramite la riga shebang (#!
).
Uso NixOS e la prima parte dello shebang in ogni script che scrivo è solitamente /usr/bin/env
. Il problema che incontro quindi è che tutto ciò che viene dopo viene interpretato come un singolo file o directory dal sistema.
Supponiamo, ad esempio, di voler scrivere uno script da eseguire da bash
in modalità posix. Il modo ingenuo di scrivere lo shebang sarebbe:
#!/usr/bin/env bash --posix
ma il tentativo di eseguire lo script risultante produce il seguente errore:
/usr/bin/env: ‘bash --posix’: No such file or directory
Sono a conoscenza di questo post, ma mi chiedevo se esistesse una soluzione più generale e più pulita.
MODIFICA :So che per gli script Guile c'è un modo per ottenere ciò che voglio, documentato nella Sezione 4.3.4 del manuale:
#!/usr/bin/env sh
exec guile -l fact -e '(@ (fac) main)' -s "$0" "[email protected]"
!#
Il trucco, qui, è che la seconda riga (che inizia con exec
) viene interpretato come codice da sh
ma, essendo nel #!
… !#
bloccare, come commento, e quindi ignorato, dall'interprete di Guile.
Non sarebbe possibile generalizzare questo metodo a qualsiasi interprete?
Seconda MODIFICA :Dopo aver giocato un po', sembra che, per gli interpreti che possono leggere il loro input da stdin
, il seguente metodo funzionerebbe:
#!/usr/bin/env sh
sed '1,2d' "$0" | bash --verbose --posix /dev/stdin; exit;
Probabilmente non è ottimale, però, come sh
il processo dura finché l'interprete non ha terminato il suo lavoro. Qualsiasi feedback o suggerimento sarebbe apprezzato.
Risposta accettata:
Non esiste una soluzione generale, almeno non se è necessario supportare Linux, perché il kernel di Linux tratta tutto ciò che segue la prima "parola" nella riga shebang come un singolo argomento.
Non sono sicuro di quali siano i vincoli di NixOS, ma in genere scriverei semplicemente il tuo shebang come
#!/bin/bash --posix
oppure, ove possibile, impostare le opzioni nello script:
set -o posix
In alternativa, puoi fare in modo che lo script si riavvii da solo con la chiamata della shell appropriata:
#!/bin/sh -
if [ "$1" != "--really" ]; then exec bash --posix -- "$0" --really "[email protected]"; fi
shift
# Processing continues
Questo approccio può essere generalizzato ad altre lingue, purché trovi un modo per ignorare le prime due righe (che vengono interpretate dalla shell) dalla lingua di destinazione.
Correlati:come aggiungere più righe a un file?
GNU coreutils
' env
fornisce una soluzione alternativa dalla versione 8.30, vedere la risposta di unode per i dettagli. (Questo è disponibile in Debian 10 e versioni successive, RHEL 8 e versioni successive, Ubuntu 19.04 e versioni successive, ecc.)