batch file - How do I get Windows cmd FOR to 'play-nice' with drag-n-drop -


i had straight forward little batch script. design outline simple enough ... want touch every file 'dropped'.

  1. there windows short-cut on desktop calls batch (.cmd) script.
  2. select files windows explorer
  3. drag-n-drop selection onto either short-cut icon or command file directly.
  4. the script loops on list of files dropped onto icon.
  5. the script uses for command call command 1 file @ time.

anyway there several circumstances result strange (to least). worst example infinite loop crashes cmd.exe. here command file. there prints , pauses here can watch behaviour.

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

the problematic output source of confusion me, see: example 1. put attrib command in because 'tame' system .exe.

when comment-out "touch" command, works attrib most of time. thing can sure file names spaces cause problems. example in echo-ed "each" lines, i've seen examples like:

  • each --> [z:\tmp\"z:\tmp\c++ recipes.pdf"]
  • "g:\_xfer_\-m"

the first seems problem loop expansion , how deals quotes("). while second appears out of bounds error msys touch.exe command.

there's fish goes on when pass link (short-cut) file script.

i've tried many different versions of both syntax , loop-variable escaping side-step issue. after primary purpose have gui touch command. first question brains trust is:

  1. what appropriate , loop-variable expansion use this?

as well, since has become mystery ....

  1. how infinite loop occur , there way prevent it?
  2. does have link documentation and/or examples of drag-n-drop window?
  3. how can script show: working folder ... g:\_xfer_ when string: "working folder", not in .cmd script. and, there once version had command: echo working folder:

it helps, put small script called, "drop.cmd" below well. final point, suspect there's bug in msys /gnu command-line handler windows:

  • it seem that, when *args passed contains string unbalanced quotes -- can go off reservation.

i similar output in example 1, below msys touch , tail commands.

i sign-off. there 1 more thing, consider. have script or diagnostic might use 'unravel' ball-of-wool?

example 1

   folder: g:\_xfer_    input:  ["g:\_xfer_\00__zip (on d).lnk" g:\_xfer_\#trash.lnk]  press key 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]            g:\_xfer_\00__zip (on d).lnk   ... g:\_xfer_\00__zip (on d).lnk   1 ... g:\_xfer_\00__zip   2 ... (on      working folder ... g:\_xfer_  touch -m -c  "g:\_xfer_\-m"     working folder ... g:\_xfer_  touch -m -c  "g:\_xfer_\-m"     :     : 

and crashed 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.   %%x  in  (%*)  (      @echo ^    raw:      [%%x]     @echo ^    each --^>  [%%~x]     @echo.     @pause ) @echo. @echo ^  [done] @echo. @pause 

getting batch file handle dropped files can difficult. dragged file spaces in name quoted, file special characters (&) without spaces not quoted. lead problems parser handling arguments file using %*.

but taking code jeb' answer , polished @dbenham solve problem of "pretty print windows %path% variable" (thank both), , retrieving arguments %* when called command line (where arguments "should" formed) or %cmdcmdline% (that hold command line used start current cmd instance) when dropped, can like

@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 command line     set "dropped="     if "%~1"=="" goto done     set var=%*     set "var=%var:"=""%"     goto :process  :dropped     rem invoked 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 dbenham's answer @ [https://stackoverflow.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=!"     %%a in ("!var:"s"s=" "!") (          if "!!"=="" endlocal          rem here have reference 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 ) 

note: sorry, not thoroughly tested. maybe there case make fail.


Comments