batch-file for-loop cmd drag-and-drop msys

batch file - ¿Cómo obtengo Windows cmd FOR para ''jugar bien'' con arrastrar y soltar?



batch-file for-loop (1)

Tenía un guión de lotes muy sencillo. El esquema de diseño es bastante simple ... Quiero tocar cada archivo '' caído ''.

  1. Hay un atajo de Windows en el escritorio que llama a un script por lotes (.cmd).
  2. Seleccione algunos archivos con Windows Explorer
  3. Arrastrar y soltar la selección en el icono de acceso directo o en el archivo de comando directamente.
  4. La secuencia de comandos pasa por encima de la lista de archivos que se han soltado en el icono.
  5. La secuencia de comandos usa el comando FOR para llamar al comando un archivo a la vez.

De todos modos, hay varias circunstancias en las que el resultado es extraño (por decir lo menos). El peor ejemplo es un bucle infinito que bloquea cmd.exe. Aquí está el archivo de comando. Hay impresiones y pausas adicionales aquí para poder ver el comportamiento.

@echo off @title touch @echo. cd > z:/$$$/base.tmp set /p base= < z:/$$$/base.tmp @rem @echo ^ folder: %base% @echo ^ INPUT: [%*] @echo. @pause @echo. for /d %%x in (%*) DO ( @echo ^ RAW: [%%x] @echo ^ each --^> [%%~x] @echo ^ each --^> [%%~fx] attrib "%%~fx" touch "%%~fx" echo. @pause echo. ) @echo. @echo ^ [done] @echo. @pause

La salida más problemática es una fuente de confusión para mí, ver: ejemplo 1. Puse el comando attrib porque es un sistema ''domestico'' .exe.

Cuando comenta el comando "tocar", el aspecto funciona solo con attrib la mayor parte del tiempo. Lo único que puedo decir con certeza es que los nombres de archivo con espacios causan problemas. Por ejemplo, en las líneas " each " de echo-ed, he visto ejemplos como:

  • each --> [Z:/tmp/"Z:/tmp/C++ Recipes.pdf"]
  • "G:/_xfer_/-m"

El primero parece ser un problema con la expansión de bucle FOR y cómo maneja las comillas ("). Mientras que el segundo parece ser un error fuera de límites con el comando MSYS touch.exe.

También hay algo que sucede cuando pasa un archivo de enlace (acceso directo) al script.

He intentado muchas versiones diferentes de la sintaxis FOR y la variable de bucle de escape para dar un paso al costado del problema. Después de todo, mi objetivo principal es tener un comando táctil GUI. Mi primera pregunta para la confianza de los cerebros es:

  1. ¿Cuál es la expansión FOR y variable de bucle apropiada para usar para esto?

Además, ya que se ha convertido en un misterio ....

  1. ¿Cómo ocurre el ciclo infinito y hay alguna forma de prevenirlo?
  2. ¿Alguien tiene un enlace para documentación y / o ejemplos de FOR con un arrastrar y soltar con Ventana?
  3. ¿Cómo puede la secuencia de comandos mostrar: Working folder ... G:/_xfer_ Cuando la cadena: "Carpeta de trabajo", que NO está en la secuencia de comandos .cmd. Y, hubo una vez una versión que tenía el comando: echo Working folder:

Es útil, puse un pequeño script llamado, "drop.cmd" a continuación también. Como punto final, sospecho que hay un error en el controlador de línea de comandos MSYS / GNU para Windows:

  • Parece que, cuando el *args que se pasó contiene una cadena con comillas no balanceadas - Puede salir de la reserva.

Obtengo un resultado similar al del ejemplo 1, a continuación, de los comandos MSYS touch y tail .

Estaba a punto de cerrar la sesión. Hay una cosa más, a considerar. ¿Alguien tiene un guión o un diagnóstico que pueda usar para ''desenredar'' esta bola de lana ?

Ejemplo 1

folder: G:/_xfer_ INPUT: ["G:/_xfer_/00__zip (on D).lnk" G:/_xfer_/#trash.lnk] Press any key to continue . . . RAW: ["G:/_xfer_/00__zip (on D).lnk"] each --> [G:/_xfer_/00__zip (on D).lnk] each --> [G:/_xfer_/00__zip (on D).lnk] A G:/_xfer_/00__zip (on D).lnk all ... G:/_xfer_/00__zip (on D).lnk one ... G:/_xfer_/00__zip two ... (on Working folder ... G:/_xfer_ touch -m -c "G:/_xfer_/-m" Working folder ... G:/_xfer_ touch -m -c "G:/_xfer_/-m" : :

¡Y finalmente se estrelló con un stackoverflow!

drop.cmd

@echo off @title %~1 @echo. cd > z:/$$$/base.tmp set /p base= < z:/$$$/base.tmp @rem @echo ^ drop folder: %base% @echo ^ INPUT: [%*] @echo. @pause rem @echo. for %%x in (%*) DO ( @echo ^ RAW: [%%x] @echo ^ each --^> [%%~x] @echo. @pause ) @echo. @echo ^ [done] @echo. @pause


Obtener un archivo por lotes maneja los archivos eliminados a veces puede ser difícil. Se citará cualquier archivo arrastrado con espacios en su nombre, pero no se citará un archivo con caracteres especiales ( & ) pero sin espacios. Esto dará lugar a problemas con el analizador al manejar los argumentos del archivo usando %* .

Pero tomando el código de jeb ''answer y pulido por @dbenham para resolver el problema de "Pretty print windows %path% variable" (gracias a los dos), y recuperando los argumentos de %* solo cuando se llama desde la línea de comando (donde los argumentos " debería " estar bien formado" o de %cmdcmdline% (que contiene la línea de comando utilizada para iniciar la instancia de cmd actual) cuando se descarta, podemos hacer algo como

@echo off setlocal enableextensions disabledelayedexpansion set "var=" rem Determine call origin setlocal enabledelayedexpansion call :detectDrop !cmdcmdline! endlocal if not errorlevel 1 goto :dropped :commandLine rem Invoked from command line set "dropped=" if "%~1"=="" goto done set var=%* set "var=%var:"=""%" goto :process :dropped rem Invoked from explorer set "dropped=1" set "var=%cmdcmdline:"=""%" set "var=%var:*/c """"=%" set "var=%var:*"" =%" set "var=%var:~0,-2%" :process if not defined var goto :done rem Adapted from dbenham''s answer at [https://.com/a/7940444/2861476] set "var=%var:^=^^%" set "var=%var:&=^&%" set "var=%var:|=^|%" set "var=%var:<=^<%" set "var=%var:>=^>%" set "var=%var: =^ ^ %" set var=%var:""="% set "var=%var:"=""Q%" set "var=%var: ="S"S%" set "var=%var:^ ^ = %" set "var=%var:""="%" setlocal enabledelayedexpansion set "var=!var:"Q=!" for %%a in ("!var:"S"S=" "!") do ( if "!!"=="" endlocal rem Here we have a reference to the passed/dropped element if %%a neq "" echo "%%~fa" ) goto :done :detectDrop cmdcmdline if /i "%~1"=="%comspec%" if /i "%~2"=="/c" exit /b 0 exit /b 1 :done if defined dropped ( pause & exit )

nota : lo siento, no probado a fondo. Tal vez haya algún caso que lo haga fallar.