2010-08-20 12 views
32

Entonces mi pregunta es ¿cómo puedo pasar un argumento de archivo a mi script bash usando un comando de Terminal en Linux? Por el momento estoy tratando de hacer un programa en bash que pueda tomar un argumento de archivo desde la Terminal y usarlo como una variable en mi programa. Por ejemplo, ejecuto myprogram --file=/path/to/file en Terminal.¿Cómo puedo pasar un argumento de archivo a mi script bash usando un comando Terminal en Linux?

Mi Programa

#!/bin/bash  
File=(the path from the argument) 
externalprogram $File (other parameters) 

¿Cómo se puede lograr esto con mi programa?

Respuesta

42

será más fácil (y más "adecuada", ver más abajo) si sólo se ejecuta la secuencia de comandos como

myprogram /path/to/file 

A continuación, puede acceder a la ruta dentro de la secuencia de comandos como $1 (por Argumento # 1, Del mismo modo $2 es el argumento # 2, etc.)

file="$1" 
externalprogram "$file" [other parameters] 

O simplemente

externalprogram "$1" [otherparameters] 

Si desea extraer la ruta de algo como --file=/path/to/file, generalmente se hace con la función de shell getopts. Pero eso es más complicado que simplemente hacer referencia a $1, y además, los conmutadores como --file= están destinados a ser opcionales. Estoy adivinando su script requiere un nombre de archivo que debe proporcionarse, por lo que no tiene sentido para pasarlo en una opción.

+3

Tenga en cuenta que todas las expansiones de los parámetros tiene que ser citado, incluyendo '$ file'. – Philipp

+0

¿Hay alguna forma de implementar el método --file? Quiero hacer eso porque si se ejecuta sin el argumento --file, el programa podría preguntar al usuario qué archivo se debe elegir. Se racionalizará el programa de esa manera. – AZorin

+2

Por lo general, solo verifica si el usuario ha proporcionado un nombre de archivo (el parámetro '#' contiene el número de argumentos posicionales), y utiliza la entrada estándar si no se proporcionó ningún archivo o '-'. Si desea la sintaxis '--file =', use una instrucción 'case'. – Philipp

7

Bash admite un concepto llamado "Parámetros posicionales". Estos parámetros posicionales representan argumentos que se especifican en la línea de comando cuando se invoca una secuencia de comandos Bash.

parámetros posicionales son referidos por los nombres $0, $1, $2 ... y así sucesivamente. $0 es el nombre de la secuencia de comandos en sí, $1 es el primer argumento de la secuencia de comandos, $2 la segunda, etc. $* representa todos los parámetros de posición, excepto para $0 (es decir, comenzando con $1).

Un ejemplo:

#!/bin/bash 
FILE="$1" 
externalprogram "$FILE" <other-parameters> 
+1

'$ FILE' debe ser citado. – Philipp

+2

Sí, tienes razón, en este caso en el que esperamos que '$ 1' contenga un nombre de archivo, se debe citar para evitar la división de palabras, si el nombre del archivo contiene uno o más espacios. ¿Pero citar los parámetros posicionales * siempre * es necesario? –

+0

Creo que es más fácil citar siempre todas las variables que adivinar si tienen que ser comillas. Los argumentos posicionales son entradas del usuario, y los usuarios pueden ingresar cualquier cosa, de modo que a menos que se documente que un argumento se somete a la división de palabras, debe citarse. Técnicamente, las variables no tienen que ser citadas después de '=' y dentro de '[[...]]', pero de nuevo es más fácil citarlas que recordar dónde no se realiza la división de palabras. – Philipp

2

Suponiendo que haces como sugiere David Zaslavsky, por lo que el primer argumento es simplemente el programa a ejecutar (sin opción de análisis requerido), que está tratando con la cuestión de cómo pasar los argumentos 2 y a su programa externo. Aquí es una forma conveniente:!.

#!/bin/bash 
ext_program="$1" 
shift 
"$ext_program" "[email protected]" 

El shift se eliminará el primer argumento, el cambio de nombre del resto ($2 convierte $1, and so on). $ @ `remite a los argumentos, como un conjunto de palabras (que debe ser citado)

Si usted debe tener su sintaxis --file (por ejemplo, si hay un programa predeterminado para funcionar, por lo que el usuario no necesariamente tiene que suministrar una), basta con sustituir ext_program="$1" con lo que el análisis de $1 que tiene que hacer, tal vez usando getopt o getopts.

Si desea rodar su propia, por sólo un caso específico, usted podría hacer algo como esto:

if [ "$#" -gt 0 -a "${1:0:6}" == "--file" ]; then 
    ext_program="${1:7}" 
else 
    ext_program="default program" 
fi 
+0

+1 para cotizar. Pero ni 'getopt' ni' getopts' pueden analizar argumentos de estilo GNU. – Philipp

+0

@Philipp: getopts no puede, pero getopt definitivamente puede, en mi sistema de todos modos. Es de suponer que eso proviene del hecho de que hay una versión GNU y otra que no es GNU de la función C 'getopt'. – Cascabel

17

puede utilizar getopt para manejar los parámetros en el script bash. no hay muchas explicaciones para getopt por ahí. aquí es un ejemplo:

#!/bin/sh 

OPTIONS=$(getopt -o hf:gb -l help,file:,foo,bar -- "[email protected]") 

if [ $? -ne 0 ]; then 
    echo "getopt error" 
    exit 1 
fi 

eval set -- $OPTIONS 

while true; do 
    case "$1" in 
    -h|--help) HELP=1 ;; 
    -f|--file) FILE="$2" ; shift ;; 
    -g|--foo) FOO=1 ;; 
    -b|--bar) BAR=1 ;; 
    --)  shift ; break ;; 
    *)   echo "unknown option: $1" ; exit 1 ;; 
    esac 
    shift 
done 

if [ $# -ne 0 ]; then 
    echo "unknown option(s): [email protected]" 
    exit 1 
fi 

echo "help: $HELP" 
echo "file: $FILE" 
echo "foo: $FOO" 
echo "bar: $BAR" 

ver también:

+1

... gran explicación – Jonathan

Cuestiones relacionadas