Características ocultas de los archivos por lotes de Windows

232

¿Cuáles son algunas de las características menos conocidas, pero importantes y útiles de los archivos por lotes de Windows?

Pautas:

  • Una característica por respuesta
  • Proporcione una breve descripción de la función y un ejemplo , no solo un enlace a la documentación
  • Limite las respuestas a la funcionalidad nativa , es decir, no requiere software adicional, como el Kit de recursos de Windows

Aclaración: aquí nos referimos a los scripts procesados ​​por cmd.exe, que es el predeterminado en las variantes de WinNT.

(Ver también: archivos por lotes de Windows: .bat vs .cmd? )

Chris Noe
fuente

Respuestas:

185

Continuación de línea:

call C:\WINDOWS\system32\ntbackup.exe ^
    backup ^
    /V:yes ^
    /R:no ^
    /RS:no ^
    /HC:off ^
    /M normal ^
    /L:s ^
    @daily.bks ^
    /F daily.bkf
Chris Noe
fuente
2
¡Estaba buscando esto la semana pasada! (no podía recordar el personaje)
chilltemp
21
El ^ es realmente una cita char. Al usarlo, puede citar <y> para que no redirijan la salida. La ^ al final de una línea también permite la continuación de la línea.
Cheeso el
¿Podrías explicarme este pequeño scriptlet?
guerda
2
@furtelwart: Esto es lo mismo que si escribió todo en una sola línea: call C:\WINDOWS\system32\ntbackup.exe backup /V:yes /R:no /RS:no /HC:off /M normal /L:s @daily.bks /F daily.bkf. Y para comprender todos los parámetros de esa línea, simplemente ejecute C:\WINDOWS\system32\ntbackup.exe /?.
Kurt Pfeifle
La discusión a fondo sobre este tema, en comandos largos se dividen en varias líneas
jeb
150
PUSHD path

Te lleva al directorio especificado por ruta .

POPD

Te lleva de vuelta al directorio desde el que "empujaste".

cuervo
fuente
55
Esto también funciona como una pila completa, por lo que puede insertar muchos directorios en la pila y luego seguir apareciendo para volver a donde estaba.
Kibbee
¿Seriamente? ¿Cómo nunca antes había oído hablar de esta función?
Josh Hinman
44
Ejecute 'cmd.exe', luego escriba 'help', luego escriba 'help pushd' o 'pushd /?'.
paxdiablo
86
Si empujó a una ruta UNC, asignará automáticamente una unidad para usted y el popd la desasignará.
Ferruccio
2
+1 especialmente para la capacidad UNC, debe agregar eso a su respuesta.
Adam Mitz
109

No estoy seguro de cuán útil sería esto en un archivo por lotes , pero es un comando muy conveniente para usar en el símbolo del sistema:

C:\some_directory> start .

Esto abrirá el Explorador de Windows en la carpeta "some_directory".

He encontrado esto un gran ahorro de tiempo.

LeopardoPiel
fuente
1
bueno, yo también lo uso. Tengo un archivo "open.cmd" en uno de los directorios PATH, y lo único en ese archivo es "@start". ;)
Paulius
55
'explorer' también hace lo mismo que 'start' C: \ some_directory> explorer.
Ray
1
Tiendo a escribir esto como [inicio "". ] (entre paréntesis para mayor claridad) porque el comienzo a veces es complicado porque el primer parámetro es un título.
PAUSE del sistema
1
Si te encuentras en una Mac, open .hace lo mismo.
Grant Paul el
1
starthace mucho más que simplemente abrir la carpeta actual. Puede pasarle cualquier archivo y lo abrirá con el visor configurado. Déle una URL y se abrirá su navegador predeterminado, etc.
idbrii
87

Siempre me ha resultado difícil leer los comentarios marcados por una palabra clave en cada línea:

REM blah blah blah

Más fácil de leer:

:: blah blah blah
Chris Noe
fuente
8
Escuché que :: es más eficiente que REM porque REM intenta hacer una expansión de variable de entorno en lo que ocurre después, pero :: no lo hace.
Scott Langham el
47
De hecho, :: es solo una etiqueta con un nombre gracioso; por lo tanto, :: no funcionará si lo usa dentro de un bloque (entre paréntesis) ya que las etiquetas tampoco están permitidas allí. REM trabaja allí, por supuesto.
mihi
Sin embargo, remtenga en cuenta que es una palabra clave documentada, mientras que ::es solo un detalle de implementación. Si bien es poco probable que ::deje de funcionar, generalmente es aconsejable no confiar en el comportamiento indocumentado.
Joey
Incluso puedes usar goto :para saltar a la etiqueta. :-)y goto -)también funcionará.
Sven Marnach
79

Subcadenas variables:

> set str=0123456789
> echo %str:~0,5%
01234
> echo %str:~-5,5%
56789
> echo %str:~3,-3%
3456
Chris Noe
fuente
3
¡Feo, pero muy útil!
guerda
1
@furtelwart parece que ese podría ser el lema del lote
rzrgenesys187
esto es genial para formatear fechas (sin embargo, el problema que encontré fue que la vista / 7 y la salida xp FECHA de manera diferente)
Daniel
Tenga en cuenta que desafortunadamente, esto no se puede combinar con las variables locales de los bucles FOR ( for %a in ...) ya que no requieren el signo de porcentaje de cierre como lo hacen las variables de entorno; primero debe asignarlos a una variable de entorno (¡usando expansión demorada!) y luego extraer una subcadena.
RolKau
Esto es inevitablemente feo si desea hacer algo con las fechas (por ejemplo, nombres de archivos de respaldo). Después de presenciar la fealdad general de la línea de comandos de Windows, veo por qué Windows es principalmente apuntar y hacer clic :) Aunque dicen que el nuevo PowerShell es mejor.
Halil Özgür
72

El comando FOR ! Si bien odio escribir archivos por lotes, estoy agradecido por ello.

FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do @echo %i %j %k

analizaría cada línea en myfile.txt, ignorando las líneas que comienzan con un punto y coma, pasando la segunda y tercera ficha de cada línea al cuerpo, con fichas delimitadas por comas y / o espacios. Observe que las declaraciones del cuerpo for hacen referencia a% i para obtener el segundo token,% j para obtener el tercer token y% k para obtener todos los tokens restantes después del 3er.

También puede usar esto para iterar sobre directorios, contenidos de directorio, etc.

TheSoftwareJedi
fuente
44
He encontrado que los bucles FOR de los archivos por lotes son limitados y terribles de escribir, pero a veces son útiles.
ya23
2
Disculpe mi desconcierto, pero ¿cómo demonios está esto infrautilizado? Creo que si no conoce los bucles FOR, no conoce las secuencias de comandos por lotes.
Codificación con estilo
11
Subutilizado o no, es una tortura. (Algunos argumentarían un mal necesario.)
harpo
Tuve que usarlo varias veces y la persona que creó esta sintaxis debería ser despedida. De un cañón. Dentro del sol. Es así de malo.
VitalyB
1
@CodingWithStyle: cada vez que necesito escribir un bucle for en un archivo por lotes, el script se convierte en un lanzador bash y reescribe el script en bash (o python) en su lugar
:)
60

En lugar de llenar una secuencia de comandos con REM o :: líneas, hago lo siguiente en la parte superior de cada secuencia de comandos:

@echo OFF
goto :START

Description of the script.

Usage:
   myscript -parm1|parm2 > result.txt

:START

Observe cómo puede usar los caracteres de canalización y redirección sin escapar de ellos.

Patrick Cuff
fuente
3
Sería aún más genial si marcaras el% 1 para "/?" y luego podrías repetir esa sección como texto de ayuda.
demoncodemonkey
66
Hmm, ¿programación literaria alfabetizada?
Muhammad Alkarouri
54

La ruta (con unidad) donde está el script: ~ dp0

set BAT_HOME=%~dp0
echo %BAT_HOME%
cd %BAT_HOME%
RealHowTo
fuente
Usualmente uso% CD% para esto. ¿Quizás no está disponible en todas las versiones de shell de DOS?
Saul Dolgin el
11
% CD% es el directorio actual, mientras que% ~ dp0 es el directorio donde se encuentra el script en ejecución.
RealHowTo
Además, no creo que% CD% existiera antes ... XP, tal vez. Sé que algunas versiones anteriores de Windows no lo tienen.
Thomas Owens
1
Debería usar cd / d% BAT_HOME% en su lugar, si el bate está en otra unidad. Sin embargo, si no recuerdo mal, esto no funcionará con DOS anteriores.
ketorin el
cd o pushd% BATH_HOME% no funcionará si ejecuta un lote en una ruta de red.
Benoit
49

La pieza% ~ dp0 ya se mencionó, pero en realidad hay más: los caracteres después de ~ definen la información que se extrae.
Ningún resultado de la letra en el retorno del nombre del archivo de parche
d - devuelve la letra de unidad
p - devuelve la ruta
s - devuelve la ruta corta
x - devuelve la extensión del archivo
Entonces, si ejecuta el script test.bat a continuación desde c: \ Temp \ nombre de directorio largo \ carpeta,

@echo off
echo %0
echo %~d0
echo %~p0
echo %~dp0
echo %~x0
echo %~s0
echo %~sp0

obtienes el siguiente resultado

test
c:
\Temp\long dir name\
c:\Temp\long dir name\
.bat
c:\Temp\LONGDI~1\test.bat
\Temp\LONGDI~1\

Y si se pasa un parámetro a su script como en la
prueba c: \ temp \ mysrc \ test.cpp,
se pueden hacer las mismas manipulaciones con la variable% 1.

¡Pero el resultado de la expansión de% 0 depende de la ubicación!
En el "nivel superior" del lote, se expande al nombre de archivo del lote actual.
En una función (llamada), se expande al nombre de la función.

@echo off
echo %0
call :test
goto :eof

:test
echo %0
echo %~0
echo %~n0

La salida es (el archivo por lotes se inicia con myBatch.bat)

myBatch.bat
:test
:test
myBatch
Hartmut
fuente
43

Al usar CALL, EXIT / B, SETLOCAL & ENDLOCAL puede implementar subrutinas con variables locales.

ejemplo:

@echo off

set x=xxxxx
call :sub 10
echo %x%
exit /b

:sub
setlocal
set /a x=%1 + 1
echo %x%
endlocal
exit /b

Esto imprimirá

11
xxxxx

aunque: sub modifica x.

Ferruccio
fuente
66
Debería usar goto: eof en lugar de exit / b, hace lo mismo pero es la forma más estándar de hacerlo.
Philibert Perusse, el
2
Hay un estándar para esto? O_o
Paulius
3
Mi error. Pensé que te referías a definir explícitamente una etiqueta: eof y hacer un goto a eso. No me di cuenta de que hay una etiqueta implícita: eof al final de cada archivo por lotes.
Ferruccio
3
Sin embargo, si desea que una subrutina establezca un nivel de error, deberá usar exit / b. Por ejemplo: exit / b 3
Chris Noe
66
He encontrado que es mejor usar "exit / B" en lugar de "goto: eof" para regresar de una subrutina, "goto: eof" tiene el problema de que puede devolver un código de error cuando quiera tragarlo. Por ejemplo, si usa "if exist someFile echo is here", esto establecerá el nivel de error si someFile no existe, pero eso no está mal y no es un código de error que desea devolver (que es lo que " goto: eof "haría).
Scott Langham el
42

Truco astuto para esperar N segundos (no es parte de cmd.exe pero no es un software adicional ya que viene con Windows), vea la línea de ping. Necesita N + 1 pings ya que el primer ping se ejecuta sin demora.

    echo %time%
    call :waitfor 5
    echo %time%
    goto :eof
:waitfor
    setlocal
    set /a "t = %1 + 1"
    >nul ping 127.0.0.1 -n %t%
    endlocal
    goto :eof
paxdiablo
fuente
2
Aún mejor es poner esto en un archivo como sleep.bat para evitar la molestia de reescribirlo una y otra vez.
erjiang
1
... y poner el sleep.bat en algún directorio en la variable de entorno PATH
Scoregraphic
Estoy en contra de poner esto afuera, hace que sea menos portátil ... en los sistemas Windows.
sorin
37

Escapar de la "fontanería":

echo ^| ^< ^> ^& ^\ ^^
Chris Noe
fuente
3
Apuesto a que el carácter de escape de DOS no se conoce bien. Bueno
Joshua
12
Ah, eso explicaría por qué también es el operador de continuación de línea: se escapa de la nueva línea, al igual que \ in bash ...
leander
@leander: Sí, pero solo puede escapar del LF (y no del CR), porque todos los CR se eliminan antes
jeb
Entonces esta es la razón por el uso de Git en Windows para diff en contra de la confirmación anterior ( HEAD^) es problemático.
Daniel Trebbien
31

Ser capaz de ejecutar comandos y procesar la salida (como los backticks de '$ ()' en bash).

for /f %i in ('dir /on /b *.jpg') do echo --^> %i

Si hay espacios en los nombres de archivo, use esto:

for /f "tokens=*" %i in ('dir /on /b *.jpg') do echo --^> %i
paxdiablo
fuente
2
No funciona con nombres de archivos que tienen espacios en sus nombres ... Esto funciona: para / f "tokens = *"% i in ('dir / on / b * .jpg') do echo - ^>% i
doekman
Buena atrapada. Personalmente, creo que los espacios en los nombres de los archivos son cosas horribles y horribles de las profundidades del noveno círculo del Infierno. Pero deberíamos atenderlos, supongo.
paxdiablo
Esa es la sintaxis más loca que he visto hasta ahora. ¿Funciona si hiciste este backtick.bat y pasaste la cadena?
idbrii
30

Crear un archivo vacío:

> copy nul filename.ext
nzpcmad
fuente
66
@devio: echo. pone una línea vacía ¡para que el archivo no esté vacío!
Paulius
44
Yo uso type nul > filename.extpara eso.
Benoit
Agradable, me preguntaba si había un toque táctil durante mucho tiempo.
jdelator
Siempre he usadoren > blah.txt
Synetech
28

Para ocultar toda la salida de un comando, redirija a> nul 2> & 1.

Por ejemplo, algunos programas de línea de comandos muestran resultados incluso si redirige a> nul. Pero, si redirige la salida como la línea de abajo, se suprimirá toda la salida.

PSKILL NOTEPAD >nul 2>&1

EDITAR: Consulte Ignorar la salida de un comando para obtener una explicación de cómo funciona esto.

revs aphoria
fuente
1
¿Sabes cómo funciona esto? ¿Cuál es el significado de 2> y 1 bit?
Scott Langham el
12
El> nul redirige STDOUT a nul. El 2> & 1 redirige STDERR a donde STDOUT está apuntando.
aphoria
Específicamente, creo que el 2> & 1 es un "clon de control de archivo", configurando STDERR en un clon de STDOUT. Ponerlo después del> NUL es importante, porque quieres clonar STDOUT después de que haya sido redirigido, no antes. (Por favor, corríjanme si me equivoco aquí.)
Leander
1
Para aquellos de ustedes que se preguntan de dónde viene PSKILL, visiten sysinternals.com . Si está en una edición Pro, debe tener un comando TSKILL nativo que sea más o menos igual.
Codificación con estilo
1
Si no tiene pskill o tskill, la mayoría de los sistemas Windows que he usado vienen con taskkill.
idbrii
25
PAUSE

Detiene la ejecución y muestra el siguiente mensaje:

Pulse cualquier tecla para continuar . . .

Es útil si desea ejecutar un lote haciendo doble clic en el Explorador de Windows y desea ver realmente el resultado en lugar de solo un destello de la ventana de comandos.

cuervo
fuente
Difícilmente llamaría a esto "infrautilizado", ya que lo etiqueto al final de cada script que escribo. Por otra parte, no funciona tan bien cuando desea que su IDE ejecute el script y capture la salida, ya que el IDE no tiene forma de presionar enter para usted generalmente ...
Nicholas Flynt
15
Una característica interesante de "pausa" es que si no hay una terminal alrededor para recibir una "clave" (por ejemplo, si su archivo por lotes se ejecuta desde un servicio del sistema), detecta esto y simplemente continúa ...
leander
44
+1 para Charlie Somerville, esto es tan conocido que todos los programadores de juegos 'go.bat' lo usaron a principios de los 90.
LiraNuna
66
En lugar de contaminar todos sus archivos por lotes (y hacerlos molestos de usar para los geeks de la CLI), puede usar Inicio / Ejecutar / luego escribir 'cmd / k' y el nombre del archivo por lotes. O cambie la cadena predeterminada HKCR \ batfile \ shell \ open \ command a 'cmd / k "% 1"% *'. O haga otro archivo por lotes que simplemente ejecute '@cmd / k $ *', póngalo en el escritorio y suelte sus otros archivos por lotes. Hay muchas alternativas para PAUSAR. Por favor considérelos.
PAUSA del sistema
1
@gnud: todavía puede tubería a la secuencia de comandos: echo.|batch-with-pause.battendrá el mismo efecto que pulsar la 'cualquier tecla' ...
Kurt Pfeifle
25

El equivalente de la fiesta (y otras conchas)

echo -n Hello # or
echo Hello\\c

que genera " Hello" sin una nueva línea final. Un hack de cmd para hacer esto:

<nul set /p any-variable-name=Hello

set /pes una forma de solicitar al usuario que ingrese. Emite la cadena dada y luego espera (en la misma línea, es decir, sin CRLF), para que el usuario escriba una respuesta.

<nulsimplemente canaliza una respuesta vacía al set /pcomando, por lo que el resultado neto es la cadena de solicitud emitida. (La variable utilizada permanece sin cambios debido a la respuesta vacía).

Los problemas son: no es posible generar un signo de igualdad inicial, y en Vista se eliminan los espacios en blanco iniciales, pero no en XP.

paxdiablo
fuente
18

Busque y reemplace cuando establezca variables de entorno:

> @set fname=%date:/=%

... elimina el "/" de una fecha para usar en nombres de archivo con marca de tiempo.

y subcadenas también ...

> @set dayofweek=%fname:~0,3%
SqlACID
fuente
17

Aritmética de enteros:

> SET /A result=10/3 + 1
4
Chris Noe
fuente
¿Cuánto tiempo tiene SET la capacidad de calcular? ¿Windows XP?
chakrit
1
Si se pregunta qué tan grandes pueden ser los valores, creo que esto es de 32 bits. Entonces +/- 2 mil millones.
Chris Noe
1
Creo que la pregunta era, ¿cuánto tiempo ha podido calcular SET? ¿Desde Windows XP?
Michael Myers
3
Creo que el SET de CMD.EXE ha podido calcular desde NT 3.1 más o menos. Sólo tomó un largo tiempo para que cualquier persona aviso de que cmd.exe no era exactamente el mismo que COMMAND.COM ...
RBerteig
16

Separadores de comando:

cls & dir
copy a b && echo Success
copy a b || echo Failure

En la segunda línea, el comando después de && solo se ejecuta si el primer comando es exitoso.

En la tercera línea, el comando después de || solo se ejecuta si falla el primer comando.

doekman
fuente
15

Salida de una línea en blanco:

echo.
paxdiablo
fuente
15

Puede encadenar sentencias if para obtener un efecto como un booleano de cortocircuito `y '.

if foo if bar baz
Jack
fuente
1
Esto es realmente sólo un acceso directo para la anidación de IFS: if foo ( if bar ( baz ) )(Imagínese saltos de línea después de los corchetes.)
idbrii
14

Para convertir rápidamente un archivo de texto Unicode (16 bits / char) en un archivo ASCII DOS (8 bits / char).

C:\> type unicodeencoded.txt > dosencoded.txt

Como bonificación, si es posible, los personajes están correctamente mapeados.

RealHowTo
fuente
1
Ese es un archivo ANSI DOS: ASCII es 7bit / char.
MarkJ
Lol, este es un antipatrón, es muy probable que esta conversión falle. La única codificación de 8 bits que admite Unicode es el UTF-8, pero gracias a M $ no puede tener la página de códigos UTF-8 configurada en Windows.
sorin
14

si estructura de bloque:

if "%VS90COMNTOOLS%"=="" (
  echo: Visual Studio 2008 is not installed
  exit /b
)
Ferruccio
fuente
3
Siempre y cuando sepa que las variables se expandirán de una sola vez (sin expansión retrasada), es decir, no puede usar sensiblemente% ERRORLEVEL% allí.
Duncan Smart
Tampoco puede usar etiquetas allí (que incluyen esos comentarios de estilo) porque terminará prematuramente la declaración if.
Codificación con estilo
2
@Duncan: no debes usar la pseudovariable de %ERRORLEVEL%todos modos; para eso if errorlevel <foo>está. Y eso de hecho funciona en esos bloques.
Joey
12

Expansión retardada de variables (con subcadenas incluidas).

    @echo off
    setlocal enableextensions enabledelayedexpansion
    set full=/u01/users/pax
:loop1
    if not "!full:~-1!" == "/" (
        set full2=!full:~-1!!full2!
        set full=!full:~,-1!
        goto :loop1
    )
    echo !full!
    endlocal
paxdiablo
fuente
12

No proporciona mucha funcionalidad, pero puede usar el comando de título para un par de usos, como proporcionar estado en un script largo en la barra de tareas, o simplemente para mejorar los comentarios de los usuarios.

@title Searching for ...
:: processing search
@title preparing search results
:: data processing
Hartmut
fuente
2
Interesante. Aunque a partir de entonces aparentemente pierde la característica normal, que es mostrar el comando que se está ejecutando actualmente. ¿Hay alguna manera de restablecer eso?
Chris Noe
2
technet.microsoft.com/en-us/library/bb491017.aspx dice que se puede restablecer con "título" por sí solo, pero esto no parece funcionar en Windows 7 ...
ℳ.
11

¿No tiene un editor a mano y necesita crear un archivo por lotes?

copy con test.bat

Simplemente escriba los comandos, presione Entrar para una nueva línea. Presione Ctrl-Z e Intro para cerrar el archivo.

Hartmut
fuente
44
Je, eso me lleva de vuelta.
Codificación con estilo
11

ejemplo de resta de cadenas en datey timepara obtener el archivo llamado "AAAA-MM-DD HH: MM: SS.txt"

echo test > "%date:~0,4%-%date:~5,2%-%date:~8,2% %time:~0,2%_%time:~3,2%_%time:~6,2%.txt"

Utilizo colorpara indicar si mi script termina con éxito, falla o necesita alguna entrada cambiando el color del texto y el fondo. Realmente ayuda cuando tienes alguna máquina al alcance de tu vista pero bastante lejos

color XY

donde X e Y es el valor hexadecimal de 0a F, donde X - fondo, Y - texto, cuando X = Y el color no cambiará.

color Z

cambia el color del texto a 'Z' y establece el fondo negro, 'color 0' no funcionará

para nombres de colores llama

color ?

másThanChaos
fuente
editado los _ fueron interpretados como cursiva. Buen código.
@Duncan inteligente: no es cierto, también trabaja en el Reino Unido Inglés (aunque técnicamente debería ser "color", grrr)
demoncodemonkey
10

Control total sobre la salida con espaciado y caracteres de escape .:

echo.    ^<resourceDir^>/%basedir%/resources^</resourceDir^>
paxdiablo
fuente
1
¿Cómo funciona? El punto delimita el comienzo de la salida de texto?
Chris Noe
3
"echo. x" generará "<space> x", "echo x" solo generará "x". Esto permite espacios principales. Además, el carácter de escape "^" evitará que cmd piense que todos esos caracteres "<" y ">" son redirección de E / S.
paxdiablo
1
echo (es mejor, porque echo. crea una búsqueda de archivos para un archivo llamado "echo" si este archivo existe el echo. falla, si no, entonces se ejecuta el eco interno, pero es más lento que echo (
jeb
9

TheSoftwareJedi ya mencionó el comando for, pero lo mencionaré nuevamente ya que es muy poderoso.

A continuación se muestra la fecha actual en el formato AAAAMMDD, lo uso al generar directorios para copias de seguridad.

for /f "tokens=2-4 delims=/- " %a in ('DATE/T') do echo %c%b%a
remonedo
fuente
2
Seguramente DATE / T regresa el 29/10/2008 en Europa y el 29/10/2008 en los EE. UU ... ¡por lo que puede ser necesaria alguna localización! ;-)
¡Así es! Pero puede abusar del comando de fecha para averiguar qué formato de fecha se utiliza.
remonedo
44
Es un uso excesivo de FOR, imo. Creo que solo usaría% DATE: ~ 10,4 %% DATE: ~ 4,2 %% DATE: ~ 7,2% para eso en lugar de ejecutar un comando de fecha y luego analizarlo.
Codificación con estilo