리눅스 명령행 인자: 명령어 옵션과 따옴표, 옵션 끝 표시, $1, $# 받기
Los argumentos de línea de comandos de Linux (command-line argument) son los valores que se pasan a un programa escribiéndolos después del nombre del comando, separados por espacios. Al pasar opciones, comillas, comodines y -- a un script de prueba que muestra tal cual los argumentos que recibe en un servidor AlmaLinux 9, vimos que quien separaba los argumentos era la shell y quien leía las opciones era cada comando.
La salida de abajo es exactamente la que se obtuvo con bash 5.1 en la cuenta root de un servidor AlmaLinux 9.8. Los scripts de prueba y los archivos de ejemplo se crearon en una carpeta de trabajo aparte, y la ruta /home/user/www es un valor de ejemplo.
1️⃣ ¿Qué son los argumentos de línea de comandos en Linux?
Si en la línea de comandos escribes algo como [comando arg1 arg2], la shell separa las palabras por los espacios. La primera palabra es el programa que se ejecuta, y las demás se pasan en orden a ese programa como sus argumentos.
Para ver los argumentos que llegan, creamos args.sh en la carpeta de trabajo. $0 contiene el nombre con el que se ejecutó, $# el número de argumentos, y de $1 en adelante los argumentos en orden. Los corchetes se añadieron para que se vea dónde empieza y termina cada argumento.
#!/bin/bash
echo "\$0 = $0"
echo "\$# = $#"
i=1
for a in "$@"; do
echo "\$$i = [$a]"
i=$((i+1))
doneDimos permiso de ejecución al script y lo ejecutamos con tres palabras: a, b y c.
./args.sh a b c$0 = ./args.sh
$# = 3
$1 = [a]
$2 = [b]
$3 = [c]Las tres palabras entraron en $1, $2 y $3, y $# fue 3. Si lo ejecutas escribiendo el nombre del script después de bash, $0 contiene el nombre tal como lo escribiste, args.sh.
bash args.sh a b c$0 = args.sh
$# = 3
$1 = [a]
$2 = [b]
$3 = [c]Solo $0 cambió a args.sh; los tres argumentos y el número fueron los mismos que antes.
2️⃣ Argumentos de línea de comandos y opciones de comandos
Los comandos de Linux suelen escribirse en el orden [comando -opción argumento]. Las opciones cambian cómo actúa el comando, y los argumentos indican los archivos, rutas o valores con los que trabaja.
ls -l /home/user/wwwPara la shell, -l también es solo un argumento. Al pasar las mismas palabras a args.sh, -l entró en $1 y la ruta en $2.
./args.sh -l /home/user/www$0 = ./args.sh
$# = 2
$1 = [-l]
$2 = [/home/user/www]Quien lee -l como opción es ls. Por eso la misma letra significa cosas distintas en cada comando: -n en head fija el número de líneas que se muestran, y -n en ls muestra el propietario como número en lugar de nombre.
Algunas opciones toman como valor propio la palabra que va justo después. En el comando find, -type usa f y -name usa "*.txt" como su valor; un valor que acompaña así a una opción se llama argumento de opción.
find . -type f -name "*.txt"En este comando, el . del principio es un argumento que no acompaña a ninguna opción e indica la carpeta donde empieza la búsqueda.
3️⃣ Formatos de las opciones de comandos en Linux
Las opciones cortas empiezan con un guion y son de una sola letra, y se pueden escribir varias juntas. Primero mostramos la carpeta site de la carpeta de trabajo con [ls -l -a].
ls -l -a sitetotal 8
drwxr-xr-x 3 root root 52 Oct 28 16:00 .
drwxr-xr-x 3 root root 137 Oct 29 01:20 ..
-rw-r--r-- 1 root root 17 Oct 28 16:00 .htaccess
drwxr-xr-x 2 root root 23 Oct 28 16:00 css
-rw-r--r-- 1 root root 14 Oct 28 16:00 index.htmlDespués la comparamos con diff con la salida de [ls -la], que junta las dos letras.
diff <(ls -l -a site) <(ls -la site) && echo samesameLas dos salidas no se diferenciaron en un solo carácter. Las opciones largas empiezan con dos guiones y se escriben como palabras; --all de ls es la misma opción que -a, así que [ls -l --all site] dio también el mismo resultado.
Las opciones largas se aceptan aunque escribas solo el principio, siempre que coincida con una sola opción. --al coincidía con dos opciones, --all y --almost-all, así que ls no mostró la lista y terminó con el código de salida 2.
ls --al sitels: option '--al' is ambiguous; possibilities: '--all' '--almost-all'
Try 'ls --help' for more information.Las opciones que reciben un valor pueden escribirse de varias formas. Al mostrar las dos primeras líneas de a.txt con head, la opción corta puede llevar el valor pegado, como [-n2].
head -n2 a.txtalpha
betaLa opción larga une el valor con un signo igual, como [--lines=2].
head --lines=2 a.txtalpha
betaLas cuatro formas, incluidas [-n 2] y [--lines 2] separadas por espacio, mostraron las dos líneas alpha y beta.
ls, head y cat leen sus opciones con la función getopt_long de la biblioteca de C. Al revisar los tres archivos de programa con strings, todos contenían el nombre de esta función.
Para comprobar las mismas reglas desde la shell se usa el comando getopt de util-linux. Las opciones cortas se escriben después de -o y las largas después de -l; los dos puntos detrás de una letra indican que la opción recibe un valor.
getopt -o lan: -l all,lines: -- -la -n 2 --all a.txt -l -a -n '2' --all -- 'a.txt'El -la escrito junto se dividió en -l y -a, y -n 2 se agrupó como -n con el valor 2. a.txt, que no es una opción, se movió al final, después de --.
4️⃣ Argumentos entre comillas y comodines
Un nombre de archivo con espacios debe ir entre comillas para pasarse como un solo argumento.
./args.sh "my file.txt" report.txt$0 = ./args.sh
$# = 2
$1 = [my file.txt]
$2 = [report.txt]Sin comillas, my y file.txt se separaron y $# pasó a ser 3. Si lo pasas así a ls o cat, buscarán dos archivos llamados my y file.txt.
./args.sh my file.txt report.txt$0 = ./args.sh
$# = 3
$1 = [my]
$2 = [file.txt]
$3 = [report.txt]La shell convierte los comodines en nombres de archivo antes de que el programa los reciba. Al pasar *.txt en la carpeta de trabajo, entraron por orden alfabético los cuatro archivos que terminan en .txt.
./args.sh *.txt$0 = ./args.sh
$# = 4
$1 = [a.txt]
$2 = [b.txt]
$3 = [my file.txt]
$4 = [report.txt]El "*.txt" entre comillas no lo cambió la shell y quedó como un solo argumento, letra por letra. En opciones como -name de find, donde el programa compara el patrón por sí mismo, se pasa así, entre comillas.
./args.sh "*.txt"$0 = ./args.sh
$# = 1
$1 = [*.txt]Unas comillas vacías también se pasan como un argumento vacío. Al ejecutar [./args.sh '' b], $# fue 2 y $1 quedó vacío.
5️⃣ Fin de las opciones de un comando (--)
Un argumento que empieza con guion, como un archivo llamado -n, el comando lo lee como opción. Al ejecutar [ls -n] en la carpeta dash, que solo contiene ese archivo, ls tomó -n no como nombre de archivo sino como la opción de salida numérica y mostró la lista de la carpeta.
ls -ntotal 4
-rw-r--r-- 1 0 0 10 Oct 28 16:00 -nLos argumentos escritos después de -- no se leen como opciones aunque empiecen con guion. [ls -- -n] mostró solo el nombre de archivo -n.
ls -- -n-nDentro de un mismo comando, los mismos caracteres se leen distinto antes y después de --. Al pasar -n dos veces a cat, el primer -n se leyó como la opción de números de línea y el -n después de -- como nombre de archivo, y salió el contenido del archivo con números de línea.
cat -n -- -n 1 dash fileTambién se puede añadir la ruta y escribir ./-n; en ese caso el argumento no empieza con guion y se lee como el mismo archivo -n.
Leer -- como el fin de las opciones también es una regla del lado del comando. Al pasarlo a args.sh, que no lee opciones, -- también entró tal cual en $1.
./args.sh -- -a$0 = ./args.sh
$# = 2
$1 = [--]
$2 = [-a]Las convenciones de utilidades de POSIX establecen que el primer -- que no sea argumento de opción se acepta como el fin de las opciones. Por eso, en los comandos que siguen estas convenciones, los nombres de archivo que empiezan con - se escriben después de --.
6️⃣ Recibir argumentos de línea de comandos en un script de shell
Un script de shell lee los argumentos que recibe mediante parámetros posicionales y parámetros especiales. El main(int argc, char *argv[]) de un programa en C recibe los mismos argumentos, así que puestos uno al lado del otro quedan así.
| Parámetro | Valor que contiene | Función main de C |
|---|---|---|
| $0 | Nombre del script ejecutado | argv[0] |
| $1 ~ $9 | Del primer al noveno argumento | argv[1] ~ argv[9] |
| ${10} | Desde el décimo argumento, entre llaves | argv[10] |
| $# | Número de argumentos, sin contar $0 | argc - 1 |
| "$@" | Todos los argumentos, cada uno por separado | De argv[1] hasta el final |
| "$*" | Todos los argumentos unidos en uno con espacios | — |
Un programa en Python recibe los mismos argumentos como la lista sys.argv. Al pasar tres argumentos con [python3 -c], my file.txt entre comillas entró en un solo elemento de la lista, y en el primer elemento entró -c.
python3 -c 'import sys; print(sys.argv)' a "my file.txt" -l['-c', 'a', 'my file.txt', '-l']"$@" y "$*" dan resultados distintos cuando van entre comillas dobles. Para ver la diferencia, creamos star.sh, que muestra las dos formas una tras otra.
#!/bin/bash
echo 'with "$@"'
printf ' [%s]\n' "$@"
echo 'with "$*"'
printf ' [%s]\n' "$*"Ejecutamos star.sh con tres argumentos: a, "b c" y d.
./star.sh a "b c" dwith "$@"
[a]
[b c]
[d]
with "$*"
[a b c d]"$@" pasó los tres argumentos por separado, y "$*" los unió con espacios y los pasó como uno solo.
Por eso, para pasar a otro comando los argumentos recibidos sin cambios, se usa "$@".
shift descarta $1 y adelanta una posición los argumentos restantes. Se usa en scripts que leen primero una opción y tratan el resto como una lista de archivos.
Creamos shift.sh, que muestra $1 y $# antes y después de shift.
#!/bin/bash
echo "before shift: \$1 = $1, \$# = $#"
shift
echo "after shift: \$1 = $1, \$# = $#"Ejecutamos shift.sh con tres argumentos: -v, a.txt y b.txt.
./shift.sh -v a.txt b.txtbefore shift: $1 = -v, $# = 3
after shift: $1 = a.txt, $# = 2A partir del décimo argumento se usan llaves, como en ${10}. Creamos ten.sh, que muestra $10 y ${10} uno al lado del otro.
#!/bin/bash
echo "\$10 = $10"
echo "\${10} = ${10}"Pasamos a ten.sh 11 argumentos, de la a a la k.
./ten.sh a b c d e f g h i j k$10 = a0
${10} = j$10 salió como a0, es decir, $1 seguido de un 0, y ${10} salió como el décimo argumento, j.
🔲 Simulador de argumentos de línea de comandos
En el simulador de abajo puedes pasar comillas, comodines y -- a args.sh, y escribir tú mismo comandos para ver cómo leen las opciones ls y getopt y cómo reciben los argumentos star.sh y shift.sh.
🔢 FAQ & contenido recomendado
Comodines
[Caracteres especiales de la shell] Comodines en Linux (metacaracteres)
Artículo que resume con ejemplos cómo seleccionar nombres de archivo con caracteres comodín como * y ? y con clases de caracteres.
Varios comandos
[Linux] 5 formas de encadenar comandos (punto y coma, tubería, ampersand..)
Artículo que resume cinco formas de ejecutar varios comandos en una sola línea con punto y coma, tuberías, &&, || y &.
Mostrar cadenas
Comando echo: From expansión y comillas
Artículo que resume cómo mostrar cadenas y valores de variables con echo, y sus opciones.
ℹ️ Aviso de afiliados
El contenido de este sitio incluye enlaces de afiliado. Cuando un visitante compra un producto o servicio a través de uno de ellos, el sitio recibe una comisión del vendedor. El importe que paga el comprador(baja durante las promociones ↓)no aumenta. Los precios, descuentos y existencias publicados corresponden al momento de redacción y pueden variar, así que confírmalos con el vendedor antes de comprar. Los productos se eligen y evalúan con criterios propios, y las comisiones no influyen en el orden ni en el contenido de las reseñas.