Me pregunto si existe una forma general de pasar múltiples opciones a un ejecutable a través de la línea shebang (#!
).
Uso NixOS, y la primera parte del shebang en cualquier script que escribo suele ser /usr/bin/env
. El problema que encuentro entonces es que el sistema interpreta todo lo que viene después como un único archivo o directorio.
Supongamos, por ejemplo, que quiero escribir un script para que lo ejecute bash
en modo posix. La forma ingenua de escribir el shebang sería:
#!/usr/bin/env bash --posix
pero intentar ejecutar el script resultante produce el siguiente error:
/usr/bin/env: ‘bash --posix’: No such file or directory
Conozco esta publicación, pero me preguntaba si había una solución más general y más limpia.
EDITAR :Sé que para los scripts de Guile, hay una manera de lograr lo que quiero, documentada en la Sección 4.3.4 del manual:
#!/usr/bin/env sh
exec guile -l fact -e '(@ (fac) main)' -s "$0" "[email protected]"
!#
El truco, aquí, es que la segunda línea (comenzando con exec
) es interpretado como código por sh
pero, estando en el #!
… !#
block, como un comentario, y por lo tanto ignorado, por el intérprete de Guile.
¿No sería posible generalizar este método a cualquier intérprete?
Segunda EDICIÓN :Después de jugar un poco, parece que, para los intérpretes que pueden leer su entrada desde stdin
, el siguiente método funcionaría:
#!/usr/bin/env sh
sed '1,2d' "$0" | bash --verbose --posix /dev/stdin; exit;
Sin embargo, probablemente no sea óptimo, ya que sh
el proceso vive hasta que el intérprete ha terminado su trabajo. Cualquier comentario o sugerencia será apreciada.
Respuesta aceptada:
No existe una solución general, al menos no si necesita compatibilidad con Linux, porque el kernel de Linux trata todo lo que sigue a la primera "palabra" en la línea shebang como un solo argumento.
No estoy seguro de cuáles son las restricciones de NixOS, pero normalmente escribiría su shebang como
#!/bin/bash --posix
o, cuando sea posible, establezca opciones en el script:
set -o posix
Alternativamente, puede hacer que el script se reinicie con la invocación de shell adecuada:
#!/bin/sh -
if [ "$1" != "--really" ]; then exec bash --posix -- "$0" --really "[email protected]"; fi
shift
# Processing continues
Este enfoque se puede generalizar a otros idiomas, siempre que encuentre una manera de que el idioma de destino ignore las primeras dos líneas (que son interpretadas por el shell).
Relacionado:¿Cómo agregar varias líneas a un archivo?
GNU coreutils
' env
proporciona una solución desde la versión 8.30, vea la respuesta de unode para obtener más detalles. (Esto está disponible en Debian 10 y posteriores, RHEL 8 y posteriores, Ubuntu 19.04 y posteriores, etc.)