script run que programacion por lotes how for example español ejemplos create commands comandos batch bat avanzados avanzada archivos archivo batch-file

batch-file - run - que es batch file en español



La comparación de archivos por lotes de variable con constante falla (2)

1. Depuración de un archivo por lotes

Para depurar un archivo por lotes para encontrar errores de sintaxis en el código, se recomienda ejecutar el archivo por lotes desde una ventana del símbolo del sistema después echo off modificar cada echo off para echo off echo ON o eliminarlo del archivo por lotes o comentarlo con el comando REM .

De manera predeterminada, el intérprete de comandos de Windows genera cada línea de comando o un bloque de comando completo que comienza con ( y termina con una coincidencia ) después de analizar y preprocesar en qué variables de entorno referenciadas con %variable% (expansión inmediata) ya están reemplazadas por el valor actual de la variable de entorno antes ejecutando la línea de comando / bloque.

Con @echo off en la parte superior del archivo por lotes, este comportamiento predeterminado se desactiva, por lo que @ al comienzo de la línea de comando desactiva también la salida de esta primera línea de comando. Por supuesto, eso es bienvenido cuando finaliza el desarrollo del archivo por lotes y el archivo por lotes funciona bien. Pero para la depuración de un archivo por lotes que no funciona como se esperaba, es mejor ver también las líneas de comando realmente ejecutadas por el intérprete de comandos para averiguar dónde sale inesperadamente la ejecución del archivo por lotes debido a un error.

El comportamiento de ECHO se explica muy brevemente en la salida de ayuda al ejecutar echo /? desde una ventana de símbolo del sistema.

Al abrir una ventana del símbolo del sistema, se inicia cmd.exe implícitamente con la opción /K para mantener el proceso de comando en ejecución y la ventana de la consola abierta después de que finaliza la ejecución de un archivo por lotes o una aplicación.

Una excepción es cuando el archivo por lotes contiene la exit comando sin parámetro /B porque en este caso el proceso de comando actual siempre sale independientemente de la jerarquía de llamada. exit /B es igual a goto :EOF y debe usarse en lugar de simplemente exit excepto que hay una muy buena razón para usar solo exit . exit /B y goto :EOF requiere ambas extensiones de comando como habilitado por defecto en Windows.

Al hacer doble clic en un archivo por lotes, se inicia cmd.exe con la opción /C para cerrar el proceso de comando y la ventana de la consola automáticamente cuando la ejecución de la aplicación o el archivo por lotes finaliza independientemente del motivo por el cual finalizó la ejecución de un archivo por lotes. Este comportamiento al cerrar automáticamente la ventana de la consola no es bueno para depurar un archivo por lotes porque el mensaje de error no se puede ver cuando la ejecución del archivo por lotes finaliza debido a un error de sintaxis.

Para obtener más detalles sobre las opciones del intérprete de comandos de Windows, ejecute en una ventana del símbolo del sistema el comando: cmd /?

Cómo salir intencionalmente de la ejecución de un archivo por lotes usando goto :EOF (los dos puntos aquí son importantes como excepción) o exit /B (solo un alias interno para goto :EOF ) se explica en ayuda de esos dos comandos que se muestran al ejecutar goto /? y exit /? en una ventana de símbolo del sistema.

Para depurar un archivo por lotes más grande, podría ser útil usar un goto agregado temporalmente en la parte superior del archivo por lotes para saltar a un determinado bloque y un goto :EOF para salir del procesamiento por lotes después del bloque para depurar.

Por cierto: :: es una etiqueta no válida que a menudo se usa para comentarios en archivos por lotes, ya que las líneas de etiqueta nunca se muestran en la ejecución de un archivo por lotes. Pero en el bloque de comandos de un bucle FOR no se pueden usar etiquetas porque el intérprete de comandos de Windows no puede interpretar correctamente un bucle FOR con etiquetas dentro del bloque de comandos. Por esa razón, es mejor usar el comando REM (comentario) para comentarios, ya que este comando está diseñado para comentarios en archivos por lotes y realmente funciona en cualquier parte de un archivo por lotes.

2. Error en el archivo por lotes

Al ejecutar el archivo por lotes publicado en cuestión con @ECHO OFF comentado reemplazándolo con rem @echo off (ejecute un reemplazo en el editor de texto) desde una ventana de símbolo del sistema, se puede ver fácilmente en qué línea se produce el error:

if %DiffSec% LSS 10 (ECHO "LESS 10")else %DiffSec% LSS 1 (ECHO "LESS 1")

Si el valor actual de la variable de entorno DiffSec no es inferior a 10 , el intérprete de comandos de Windows ejecuta la rama ELSE, que comienza con un número como 10 .

El intérprete de comandos de Windows no puede encontrar una aplicación con ese nombre en el directorio actual o en cualquier directorio especificado en la lista de directorios separados por punto y coma de la variable de entorno PATH tiene una extensión de archivo especificada en la lista de extensiones de archivos separados por punto y coma de la variable de entorno PATHEXT .

El error es aquí, obviamente, el comando IF faltante para la próxima comparación. Entonces el código correcto sería

if %DiffSec% LSS 10 (ECHO "LESS 10") else if %DiffSec% LSS 1 ECHO "LESS 1"

Esto sería más fácil de leer al escribir la condición en varias líneas:

if %DiffSec% LSS 10 ( ECHO "LESS 10" ) else if %DiffSec% LSS 1 ( ECHO "LESS 1" )

La sintaxis ahora es correcta.

Pero la segunda condición no tiene sentido como JosefZ ya mencionó en su comentario. Si el valor de DiffSec es 10 o mayor, lo que resulta en la ejecución del comando IF en la rama ELSE , esta condición definitivamente nunca es cierta. Entonces más sentido tendría:

if %DiffSec% LSS 1 (ECHO LESS 1) else if %DiffSec% LSS 10 ECHO LESS 10

O alternativamente

if %DiffSec% LSS 1 ( ECHO LESS 1 ) else if %DiffSec% LSS 10 ( ECHO LESS 10 )

Para obtener más información sobre condiciones IF ELSE válidas en archivos por lotes, consulte, por ejemplo, las respuestas en

  • SI ELSE error de sintaxis dentro del archivo por lotes?
  • scripting por lotes: si existe ./sdcard/file.any usando adb

3. Agregar cero a la izquierda para números <10

Las variables de entorno son siempre de tipo cadena. Para expresiones aritméticas, el valor de cadena de una variable de entorno se convierte a un entero de 32 bits con signo, si es posible, y el resultado de la expresión aritmética se convierte de nuevo a entero de 32 bits con signo.

También una condición IF como if %DiffSec% LSS 10 se expande antes de la ejecución, por ejemplo, a if 5 LSS 10 resulta en la conversión de 5 (0x35) de cadena a entero y 10 (0x31 0x30) también de cadena a entero para comparar los dos números como enteros

Por lo tanto, sería un poco más rápido evitar dicha comparación numérica si eso fuera posible.

Es bastante fácil agregar un cero inicial a un número inferior a 10 sin probar realmente el valor mediante la sustitución de cadenas.

Primero, el valor actual de la variable de entorno se antepone con uno (para un número de dos dígitos) o más 0 (para 3, 4 o incluso más dígitos).

set "DiffSec=0%DiffSec%"

A continuación, los últimos X caracteres como 2 para un número de dos dígitos se asignan del valor actual de la variable de entorno a la variable de entorno.

set "DiffSec=%DiffSec:~-2%"

La sustitución de cadenas se explica en ayuda de la salida del comando SET ejecutando en una ventana del símbolo del sistema set /? .

El resultado de las dos líneas es que DiffSec tiene para valores de 0 a 99 después de esas dos líneas siempre un número de dos dígitos en el rango de 00 a 99 .

4. Análisis de una expresión aritmética.

Una interpretación aritmética que es la cadena después de set /a es interpretada por el intérprete de comandos de Windows completamente diferente a otras cadenas.

Los espacios y las pestañas son separadores de palabras, pero no tienen más significado especial. Por lo tanto, es aconsejable utilizar espacios para que la expresión aritmética sea más legible.

Luego, hay muchos operadores que se enumeran en la ayuda del comando SET que se muestra al ejecutarse en una ventana del símbolo del sistema set /? .

Otros enteros decimales, octales y hexadecimales se interpretan en una expresión aritmética como enteros.

Y por último, cada otra cadena se interpreta como el nombre de una variable de entorno cuyo valor actual se convierte de cadena a entero.

Por esa razón, no es aconsejable utilizar la expansión inmediata o retardada en una expresión aritmética.

El valor de referencia de una variable de entorno con %variable% dentro de una expresión aritmética no es bueno cuando se usa dentro de un bloque de comandos en el que el valor actual de la variable de entorno reemplaza la referencia de la variable que ya se estaba analizando en el bloque de comandos completo antes de ejecutar el primer comando.

Valor de referencia de una variable de entorno con !variable! dentro de una expresión aritmética tampoco es bueno porque requiere habilitar la expansión retardada, lo que resulta en el manejo de signos de exclamación en cadenas que ya no son caracteres literales.

Por lo tanto, lo mejor es simplemente escribir los nombres de las variables en una expresión aritmética sin signos de porcentaje o signos de exclamación circundantes, si eso es posible porque el nombre de la variable no contiene un carácter de espacio y comienza con un carácter que Windows no puede interpretar como un número entero. intérprete de comandos.

Vea también la respuesta en ¿Por qué no hay salida de cadena con ''echo% var%'' después de usar ''set var = text'' en la línea de comando? para obtener detalles sobre cómo asignar un valor a una variable de entorno usando solo set o set /P (solicitud) o set /A (expresión aritmética).

5. Código fijo y optimizado

El código en cuestión puede repararse y optimizarse para este código:

@echo off rem Time Calculation for /F "skip=1 tokens=1-4" %%A in (''%SystemRoot%/System32/wbem/wmic.exe PATH Win32_LocalTime GET Day^,Hour^,Minute^,Second'') do ( set Day=%%A set Hour=%%B set Minute=%%C set Second=%%D ) set /A TimeStart=Day * 86400 + Hour * 3600 + Minute *60 + Second @echo on %SystemRoot%/System32/ping.exe 8.8.8.8 -n 11 @echo off for /F "skip=1 tokens=1-4" %%A in (''%SystemRoot%/System32/wbem/wmic.exe PATH Win32_LocalTime GET Day^,Hour^,Minute^,Second'') do ( set Day=%%A set Hour=%%B set Minute=%%C set Second=%%D ) set /A TimeEnd=Day * 86400 + Hour * 3600 + Minute *60 + Second set /A TimeDiff=TimeEnd - TimeStart set /A DiffSec=TimeDiff %% 60 set /A TimeDiff=(TimeDiff - DiffSec) / 60 set /A DiffMin= TimeDiff %% 60 set /A DiffHrs=(TimeDiff - DiffMin) / 60 set "DiffSec=0%DiffSec%" set "DiffSec=%DiffSec:~-2%" set "DiffMin=0%DiffMin%" set "DiffMin=%DiffMin:~-2%" set "DiffHrs=0%DiffHrs%" set "DiffHrs=%DiffHrs:~-2%" echo Time needed for orders deletion: %DiffHrs%:%DiffMin%:%DiffSec%

Para comprender los comandos utilizados y cómo funcionan, abra una ventana de símbolo del sistema, ejecute allí los siguientes comandos y lea con cuidado todas las páginas de ayuda que se muestran para cada comando.

  • echo /?
  • for /?
  • ping /?
  • rem /?
  • set /?
  • wmic /?
  • wmic path /?

Quiero escribir una simple pieza de código para obtener una buena "marca de tiempo" formateada. Poner el tiempo en mis dos variables Start y End funciona bien. También puedo imprimirlo como 0: 0: 0. Quiero tener un cero a la izquierda si es menor que 10, pero aparentemente recibo un error que dice ''el parámetro 10 no se encuentra o está mal escrito''. Descubrí que esta parece ser la variable a comparar, pero no pude solucionarlo. ¿Algunas ideas?

@ECHO OFF REM Time Calculation FOR /F "skip=1 tokens=1-6" %%A IN (''WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Second /Format:table ^| findstr /r "."'') DO ( set Day=%%A set Hour=%%B set Minute=%%C set Second=%%D ) set /a Start=%Day%*8640000+%Hour%*360000+%Minute%*6000+%Second%*100 @ECHO ON ping 8.8.8.8 -n 11 @ECHO OFF FOR /F "skip=1 tokens=1-6" %%A IN (''WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Second /Format:table ^| findstr /r "."'') DO ( set Day=%%A set Hour=%%B set Minute=%%C set Second=%%D ) set /a End=%Day%*8640000+%Hour%*360000+%Minute%*6000+%Second%*100 set /a Diff=%End%-%Start% set /a Diff=(%Diff%)/100 set /a DiffSec=%Diff%%%60 set /a Diff=(%Diff%-%Diff%%%60)/60 set /a DiffMin=%Diff%%%60 set /a Diff=(%Diff%-%Diff%%%60)/60 set /a DiffHrs=%Diff% ECHO Laufzeit Auftraege loeschen: %DiffHrs%:%DiffMin%:%DiffSec% :: format with leading zeroes if %DiffSec% LSS 10 (ECHO "LESS 10")else %DiffSec% LSS 1 (ECHO "LESS 1") ::if %DiffSec% LSS 10 (set DiffSec=0%DiffSec%)else [%DiffSec%] LSS 1 (set DiffSec=00) ::if %DiffMin% LSS 10 (set DiffMin=0%DiffMin%)else [%DiffMin%] LSS 1 (set DiffMin=00) ::if %DiffHrs% LSS 10 (set DiffHrs=0%DiffHrs%)else [%DiffHrs%] LSS 1 (set DiffHrs=00) ECHO Laufzeit Auftraege loeschen: %DiffHrs%:%DiffMin%:%DiffSec%


if %DiffSec% LSS 10 (ECHO "LESS 10")else IF %DiffSec% LSS 1 (ECHO "LESS 1")

necesitas un if después de lo else .