Una herramienta de terminal recibe lo que escribes detrás de su nombre: archivos, opciones, interruptores. En C# llega todo en el array args. Para dos opciones basta un bucle; para algo más serio, la biblioteca oficial System.CommandLine genera la ayuda y los mensajes de error por ti.
También te puede interesar
El array args
Lo que se escribe detrás del nombre del programa llega en args, un string[] que existe siempre en las instrucciones de nivel superior (es el parámetro del Main que escribe el compilador). Con dotnet run, los argumentos para tu programa van después de --; lo que va antes es para dotnet:
dotnet run lista.cs -- informe.txt --formato csv -v
Console.WriteLine($"Recibidos: {args.Length}");
for (int i = 0; i < args.Length; i++)
{
Console.WriteLine($"args[{i}] = {args[i]}");
}salidaRecibidos: 4 args[0] = informe.txt args[1] = --formato args[2] = csv args[3] = -v
La terminal parte el texto por los espacios antes de que llegue a tu programa: args no sabe qué es una opción y qué un valor, eso lo decides tú. Si un argumento lleva espacios, se escribe entre comillas en la terminal y llega como uno solo, sin ellas. Sin el --, dotnet intentaría interpretar --formato como una opción suya.
Leer opciones a mano
Para dos o tres opciones no hace falta nada más que un bucle y un switch con patrones:
string? archivo = null;
string formato = "texto";
bool detalle = false;
for (int i = 0; i < args.Length; i++)
{
switch (args[i])
{
case "--formato" when i + 1 < args.Length:
formato = args[++i];
break;
case "-v" or "--detalle":
detalle = true;
break;
case var a when a.StartsWith('-'):
Console.Error.WriteLine($"Opción desconocida: {a}");
return 2;
default:
archivo = args[i];
break;
}
}
if (archivo is null)
{
Console.Error.WriteLine("Uso: informe <archivo> [--formato csv|texto] [-v]");
return 1;
}
Console.WriteLine($"archivo={archivo} formato={formato} detalle={detalle}");
return 0;dotnet run manual.cs -- ventas.txt --formato csv -v
salidaarchivo=ventas.txt formato=csv detalle=True
Con una opción que no existe:
dotnet run manual.cs -- ventas.txt --colores
salidaOpción desconocida: --colores
Dos detalles que distinguen una herramienta seria. Los errores van a Console.Error (la salida de errores), no a la normal, para que no se mezclen con los datos si alguien redirige la salida a un archivo. Y el programa devuelve un código: 0 si todo fue bien y otro número si no. Con instrucciones de nivel superior basta un return con un entero; los scripts y las tuberías de integración continua lo miran para saber si algo falló (en la terminal, con echo $?).
Con System.CommandLine
En cuanto hay subcomandos, valores con tipo o ayuda, conviene la biblioteca oficial de Microsoft, System.CommandLine, la misma que usa la herramienta dotnet. Su versión 2.0, estable desde finales de 2025, tiene una API más sencilla que las versiones preliminares que circularon años por ahí, así que cuidado con los ejemplos antiguos:
#:package System.CommandLine@2.0.14
using System.CommandLine;
var nombre = new Argument<string>("nombre") { Description = "A quién saludar" };
var veces = new Option<int>("--veces", "-n") { Description = "Cuántas veces", DefaultValueFactory = _ => 1 };
var gritar = new Option<bool>("--gritar") { Description = "En mayúsculas" };
var raiz = new RootCommand("Saluda a alguien desde la terminal.") { nombre, veces, gritar };
raiz.SetAction(resultado =>
{
string saludo = $"Hola, {resultado.GetValue(nombre)}";
if (resultado.GetValue(gritar)) saludo = saludo.ToUpper();
for (int i = 0; i < resultado.GetValue(veces); i++)
{
Console.WriteLine(saludo);
}
});
return raiz.Parse(args).Invoke();dotnet run saludar.cs -- Ana --veces 2 --gritar
salidaHOLA, ANA HOLA, ANA
Cada Argument y cada Option lleva su tipo: GetValue(veces) devuelve un int, ya convertido. DefaultValueFactory da el valor si no se escribe la opción, y una Option<bool> es un interruptor que vale true solo con aparecer. La ayuda se genera sola:
dotnet run saludar.cs -- --help
salidaDescription: Saluda a alguien desde la terminal. Usage: saludar <nombre> [options] Arguments: <nombre> A quién saludar Options: -n, --veces <veces> Cuántas veces [default: 1] --gritar En mayúsculas -?, -h, --help Show help and usage information --version Show version information
Y los errores de conversión también. Los textos de la ayuda que pone la biblioteca («Usage», «Show help…») están en inglés; las descripciones son las tuyas:
dotnet run saludar.cs -- Ana --veces dos
salidaCannot parse argument 'dos' for option '--veces' as expected type 'System.Int32'. Description: Saluda a alguien desde la terminal. Usage: saludar <nombre> [options] Arguments: <nombre> A quién saludar Options: -n, --veces <veces> Cuántas veces [default: 1] --gritar En mayúsculas -?, -h, --help Show help and usage information --version Show version information
#:package, se añade con dotnet add package System.CommandLine. Y si quieres instalar tu herramienta para usarla desde cualquier carpeta, dotnet pack con <PackAsTool>true</PackAsTool> en el .csproj la convierte en una herramienta de .NET que se instala con dotnet tool install.Todo el código de esta página se compiló con el .NET SDK 10.0.403 (C# 14) y se ejecutó con .NET 10.0.14 en un contenedor limpio antes de publicarla; las salidas y los mensajes del compilador están copiados de esa ejecución.