Anatomía de un comando: nombre, flags y argumentos

Cada vez que escribes algo en la terminal y pulsas Enter, la shell lo descompone en piezas antes de ejecutarlo. Esa descomposición no es arbitraria: sigue una convención que casi todos los programas Unix respetan, y entenderla te permite usar cualquier comando nuevo con mucha menos fricción.

Un comando tiene tres partes fundamentales. El nombre del comando es simplemente el programa que se va a ejecutar —ls, cp, git— y la shell lo busca en los directorios listados en $PATH. Las flags (también llamadas opciones) son interruptores que modifican el comportamiento del programa. Los argumentos posicionales son los datos sobre los que el programa trabaja: archivos, rutas, nombres de usuario.

¿Por qué existe esta distinción? Porque los programas necesitan dos tipos de información diferentes: cómo comportarse (flags) y con qué trabajar (argumentos). Un programa como ls puede mostrar los archivos en formato largo, incluir los ocultos, ordenar por fecha… todo eso es comportamiento. La ruta que le pasas es el dato. Mantenerlos separados hace que los programas sean componibles y predecibles.

Usas flags cuando necesitas cambiar el modo de operación por defecto. Usas argumentos cuando el programa necesita saber sobre qué actuar. Y si te equivocas en la sintaxis —por ejemplo, poner el argumento antes de la flag cuando el programa no lo espera así—, obtendrás un error críptico o, peor, un resultado silenciosamente incorrecto.

Las flags vienen en dos sabores. Las flags cortas van precedidas de un guión simple (-l, -a, -h) y se pueden combinar detrás de un solo guión: -la es exactamente igual que -l -a. Las flags largas llevan doble guión (--all, --human-readable) y no se pueden combinar, pero son mucho más legibles en scripts. Algunos programas ofrecen ambas formas para la misma opción; otros solo una.

Hay un caso especial que vale la pena entender bien desde el principio: la convención --. Cuando escribes -- en la línea de comandos, le dices al programa “aquí terminan las flags; lo que viene después son argumentos, pase lo que pase”. Esto es crítico cuando un nombre de archivo empieza por guión. Si tienes un archivo llamado -f e intentas borrarlo con rm -f, no borrarás ese archivo: -f será interpretado como la flag “force”. La solución es rm -- -f.

Otro matiz importante: algunas flags son booleanas (están activas o no), y otras toman un valor. En ls -la, -l y -a son booleanas. Pero en git commit -m "mensaje inicial", la flag -m toma un argumento: el mensaje del commit. Ese argumento va pegado a continuación, separado por espacio. Con flags largas, el valor puede ir separado por espacio o por =: --message="mensaje inicial" y --message "mensaje inicial" son equivalentes en la mayoría de herramientas.

Ejemplo completo

# Listar el contenido de /etc con detalle, incluyendo ocultos,
# y tamaños legibles por humanos
ls -lah /etc

# La misma operación con flags largas (más legible en un script)
ls --all --human-readable -l /etc

# Buscar la cadena "--version" dentro de un archivo llamado notas.txt
# Sin el --, grep intentaría interpretar --version como una flag suya
grep -- "--version" notas.txt

# Crear un commit con mensaje: -m toma el mensaje como su valor
git commit -m "Corrige error de validación en formulario de login"

# Ejemplo con valor pegado via = (equivalente al anterior en git)
git commit --message="Corrige error de validación en formulario de login"

# Archivo con nombre problemático: sin -- esto fallaría o haría algo inesperado
touch -- -archivo-raro.txt
ls -la -- -archivo-raro.txt
rm -- -archivo-raro.txt

Desglose

En ls -lah /etc, las tres letras detrás del guión son tres flags booleanas combinadas: -l activa el formato largo, -a incluye entradas que empiezan por punto (los archivos ocultos), y -h hace que los tamaños aparezcan como 4,0K en lugar de 4096. El argumento posicional /etc le dice a ls sobre qué directorio actuar. Si lo omites, ls usa el directorio actual por defecto.

La línea con ls --all --human-readable -l /etc hace exactamente lo mismo. Fíjate que -l no tiene equivalente largo universalmente aceptado en la versión de ls de GNU coreutils, así que se mezclan estilos. Eso es perfectamente válido.

El bloque de grep -- "--version" notas.txt ilustra por qué -- existe. Sin él, grep vería --version, asumiría que es una opción de grep mismo, e imprimiría su versión en lugar de buscar dentro del archivo. El -- corta esa interpretación: todo lo posterior es argumento, sin excepciones.

En git commit -m "Corrige error...", el par -m valor muestra la mecánica de flags que consumen un argumento. git sabe que -m siempre va seguida de un texto, así que toma la siguiente cadena como el mensaje. Si escribes -m sin nada después, git dará error porque le falta el valor que espera.

El bloque final con -archivo-raro.txt es un caso real que aparece cuando trabajas con archivos generados automáticamente o sincronizados desde otros sistemas. touch -- -archivo-raro.txt crea el archivo sin que touch intente interpretar -archivo-raro como flags. El mismo -- es necesario en ls y rm para manejarlo. Interioriza este patrón: cada vez que un nombre de archivo empiece por guión, -- es tu herramienta.

11

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio