Encadenar comandos
En el símbolo del sistema, los símbolos &, && y || permiten ejecutar varios comandos en una sola línea.
Puedes escribir cosas como “crear una carpeta y entrar en ella” o “mostrar un mensaje y salir si la copia falla” sin usar IF, por lo que el encadenamiento es habitual tanto en archivos por lotes como en la línea de comandos.
Operadores de encadenamiento
| Símbolo | Nombre | Comportamiento |
|---|---|---|
& | Incondicional | Ejecuta el siguiente comando sin importar el resultado del anterior |
&& | AND (si tiene éxito) | Ejecuta el siguiente solo si el anterior tuvo éxito (código de salida 0) |
|| | OR (si falla) | Ejecuta el siguiente solo si el anterior falló (código de salida distinto de 0) |
El éxito o el fallo se determina por el código de salida (ERRORLEVEL). Para más detalles, consulta el artículo sobre ERRORLEVEL.
Ejecutar en secuencia con &
& ejecuta el siguiente comando tanto si el anterior tuvo éxito como si falló.
comando1 & comando2
echo %DATE% & echo %TIME%
Si hay un espacio justo antes de &, como en echo %DATE% , ese espacio forma parte de la salida. Si necesitas la salida exacta, quita el espacio: echo %DATE%& echo %TIME%.
Ejecutar solo si tiene éxito con &&
&& ejecuta el siguiente comando solo si el anterior tuvo éxito. Úsalo para encadenar pasos que dependen de que el paso anterior haya terminado correctamente.
mkdir work && cd work
Si mkdir falla (por ejemplo, por falta de permisos o porque ya existe una carpeta o archivo con el mismo nombre), cd work no se ejecuta. Ten en cuenta que, si la carpeta work ya existe, al ejecutar de nuevo este comando mkdir falla y tampoco se ejecuta cd work.
copy "report.txt" "D:\backup\report.txt" && del "report.txt"
Así se evita el accidente de borrar el archivo original cuando la copia ha fallado.
Ejecutar solo si falla con ||
|| ejecuta el siguiente comando solo si el anterior falló. Es útil para mostrar mensajes de error o interrumpir un proceso.
ping -n 1 192.168.1.1 | find "TTL=" >nul || echo Sin respuesta
Salir de un archivo por lotes antes de tiempo
En los archivos por lotes, el patrón || exit /b 1 se usa mucho para detener el procesamiento cuando se produce un error.
@echo off
cd /d "D:\project" || exit /b 1
copy "config.ini" "config.bak" || exit /b 1
echo Preparación completada
exit /b 1 finaliza el archivo por lotes con el código de salida 1. Para más detalles, consulta
Combinar && y ||
Al combinar ambos puedes ramificar según el éxito o el fallo.
tasklist | find "notepad.exe" >nul && echo En ejecución || echo No está en ejecución
find devuelve el código de salida 0 si encuentra una línea coincidente y 1 si no la encuentra, por lo que es adecuado para comprobar si existe un proceso o un texto. En otros errores (como un archivo inexistente) devuelve 2, pero || trata cualquier código distinto de 0 como fallo, así que en esos casos también se ejecuta el lado “No está en ejecución”.
Es tentador leer A && B || C como “B si A tiene éxito, y C en caso contrario”, pero C también se ejecuta si A tiene éxito y B falla.
copy "a.txt" "b.txt" && findstr "xyz" "nofile.txt" >nul 2>&1 || echo La copia fallóEn el ejemplo anterior, aunque la copia tenga éxito, el segundo comando (aquí, un findstr sobre un archivo inexistente) falla, por lo que se muestra “La copia falló”. Cuando necesites una ramificación estricta, usa
Orden de evaluación
&& y || tienen la misma precedencia y se evalúan de izquierda a derecha. Un comando omitido porque no se cumplió su condición transmite el resultado anterior.
cd /d C:\Windows || echo A && echo B
Si cd tiene éxito, echo A se omite, pero el resultado de “éxito” se transmite, por lo que echo B se ejecuta. Además, & tiene menor precedencia que && y ||: A & B && C se interpreta como “ejecutar A y después B && C”. La tubería | y la redirección se asocian con más fuerza que todos estos operadores. Las combinaciones complejas se comportan fácilmente de forma inesperada, así que usa la agrupación con paréntesis que se explica a continuación.
Agrupar con paréntesis
Si encierras varios comandos entre paréntesis ( ), se tratan como una unidad.
copy "data.csv" "backup\" >nul || (
echo La copia de seguridad falló
exit /b 1
)
del "data.csv"
Si escribes A && (si tiene éxito) || (si falla), el bloque de fallo también se ejecuta cuando falla el último comando del bloque de éxito. Agrupar con || solo el tratamiento del fallo, como arriba, es la forma más segura.
(echo Fecha: %DATE% & echo Hora: %TIME%) > log.txt
Si aplicas una redirección a todo el grupo, como en (echo Fecha: %DATE% & echo Hora: %TIME%) > log.txt, toda la salida estándar del grupo se guarda en el archivo (añade 2>&1 para guardar también la salida de error). Sobre la redirección, consulta el artículo sobre redirección.
Dividir una cadena larga en varias líneas
Cuando una cadena se vuelve larga y difícil de leer, coloca ^ al final de la línea. Esto escapa el salto de línea y la línea siguiente continúa la misma línea de comandos. No pongas espacios después de ^ ni una línea en blanco justo a continuación.
mkdir "work" ^
&& cd "work" ^
&& echo La carpeta de trabajo está lista
Para saber cómo usar ^, consulta el artículo sobre escape.
Aspectos a tener en cuenta
Una variable definida en la misma línea no se puede referenciar en ella
cmd analiza la línea completa antes de ejecutarla, por lo que si haces referencia a una variable con %nombre% en la misma línea donde la defines, se sustituye por el valor anterior a la asignación.
set MSG=Hello & echo %MSG%
Como toda la línea se analiza primero, a echo se le pasa el valor de MSG en el momento del análisis (vacío si no está definida en un archivo por lotes, o el texto literal %MSG% en la línea de comandos), por lo que no se muestra Hello. Para evitarlo, activa setlocal EnableDelayedExpansion en un archivo por lotes (o cmd /v:on en la línea de comandos) y escribe !MSG!, o coloca los comandos en líneas separadas. Para más detalles, consulta
Espacio adicional en el valor de set
Si escribes set MSG=Hello & echo ..., el valor de MSG pasa a ser Hello (con un espacio al final), porque el espacio anterior a & se incluye en el valor. Encierra la asignación entre comillas dobles: set "MSG=Hello" & echo ....
Encadenar después de un IF
Los comandos encadenados con & o && después del cuerpo de un IF también se ejecutan solo cuando la condición del IF es verdadera.
if exist "a.txt" echo Encontrado & echo Procesando
Si a.txt no existe, no se ejecuta ninguno de los dos echo. Como la intención resulta difícil de leer, encierra varios comandos entre paréntesis.
Comandos como robocopy que devuelven un valor distinto de 0 al tener éxito
puede devolver un código de salida distinto de 0 incluso con éxito, por ejemplo 1 cuando se copiaron archivos (8 o más indica un error). Con estos comandos,&& y || no pueden juzgar el resultado correctamente.
robocopy "src" "dst" /E
if %ERRORLEVEL% GEQ 8 echo La copia falló
Tratamiento de los caracteres especiales
& y | son caracteres especiales en el símbolo del sistema. Para mostrarlos como caracteres literales, escápalos, como en echo A ^& B. Encerrar el texto entre comillas dobles también funciona, pero echo "A & B" imprime también las comillas. Además, | (
|| (OR), y & y &&, son operadores distintos, así que no los confundas.
Diferencias en PowerShell
&& y || no están disponibles en Windows PowerShell 5.1 (sí lo están en PowerShell 7 y posteriores). La sintaxis de este artículo describe el símbolo del sistema (cmd.exe).
Ejemplos prácticos
Moverse a una carpeta de otra unidad y listar su contenido
cd /d "D:\project" && dir /b
Crear una carpeta si no existe
if not exist "logs" mkdir "logs"
En este caso es más adecuado usar IF que encadenar. Consulta también el artículo sobre comprobar si existe un archivo.
Continuar aunque un comando falle
Con &, el siguiente comando se ejecuta aunque el anterior haya fallado.
taskkill /im notepad.exe >nul 2>&1 & timeout /t 3 /nobreak >nul
Ejercicios
Resumen
| Objetivo | Sintaxis |
|---|---|
| Ejecutar en orden sin importar el resultado | A & B |
| Ejecutar el siguiente solo si hay éxito | A && B |
| Ejecutar el siguiente solo si hay fallo | A || B |
| Salir del archivo por lotes si falla | A || exit /b 1 |
| Tratar varios comandos como una unidad | (A & B) && C |
| Dividir una cadena larga en líneas | ^ al final de línea |
&&y||se deciden por el código de salida del comando anteriorA && B || Cno sustituye a un if-else; usaIFpara ramificar de forma estricta- Una variable definida en la misma línea no se puede referenciar con
%var%sin expansión retardada - Los comandos como
robocopy, que devuelven un valor distinto de 0 al tener éxito, no se pueden juzgar correctamente con&&ni||