rubberman
Goto Top

Batch - Drag And Drop Files - Ampersand Bug

Hallo Community.

Wie man weiß, kann man Parameter in einer Batchtatei über die Ausdrücke %1 bis %9 abgreifen, bzw. mit %* um gleich alle Parameter zu bekommen. Bei dragged/dropped Dateien gibt es dabei einen Bug, der nie gefixt wurde:
Alle auf diese Weise übergebenen Dateien kommen mit dem kompletten Pfad an. Sollte im Pfad oder im Dateiname ein Leerzeichen vorhanden sein, werden die Parameter automatisch in Anführungszeichen gesetzt und die Verarbeitung funktioniert problemlos. Alle Parameter ohne Leerzeichen kommen ohne umschließende Anführungszeichen. Das macht die Verarbeitung von Pfaden/Dateien mit einem & unmöglich. Hierbei wird am & Zeichen abgebrochen, unabhängig davon, ob nachträglich im Code Anführungszeichen eingefügt werden (zB. "%~1") oder nicht. Ein Workaround für diesen Bug ist die Verarbeitung der Umgebungsvariable %CMDCMDLINE%. Hier gibt es dann aber Probleme, wenn die übergebenen Dateipfade FOR-Trennzeichen wie ',' ';' '=' enthalten. Eine Reihe an Stringersetzungen ist nötig, um am Ende jeden Parameter in Anführungszeichen zu setzen um eine problemlose Verarbeitung zu ermöglichen...
Soviel zur langen Vorrede, nun aber mal zum Code, der zeigt wie die Umsetzung aussieht face-wink
(Darauf achten, dass sich nach dem letzten % in Zeile 13 kein Leerzeichen einmogelt!)
@echo off &setlocal DisableDelayedExpansion

setlocal EnableDelayedExpansion
set "params=!cmdcmdline:~,-1!"  
set "params=!params:*" =!"  

if "!params!"=="" exit  

endlocal&set "params=%params:"=""%"  
set "params=%params:^=^^%"  
set "params=%params:&=^&%"  
set "params=%params: =^ ^ %"  
set params=%params:""="%  
set "params=%params:"=""Q%"  
set "params=%params:  ="S"S%"  
set "params=%params:^ ^ = %"  
set "params=%params:""="%"  

setlocal EnableDelayedExpansion
set "params=!params:"Q=!"  

for %%i in ("!params:"S"S=" "!") do (  
  if "!!"=="" endlocal  
  REM Nur Dateien sollen verarbeitet werden.
  if not exist "%%~i\" (  
    set "file=%%~i"  
    call :proc
  )
)

echo Fertig.
pause
exit


:proc
echo Verarbeite "%file%" hier ...  
goto :eof
Ausnahmsweise kommen hier mal EXITs zum Einsatz, um Fehlermeldungen zu unterdrücken.

Referenzen:
www.dostips.com/forum/viewtopic.php?f=3&t=5479
stackoverflow.com/questions/1243240/drag-and-drop-batch-file-for-multiple-files/5370380#5370380
stackoverflow.com/questions/5471556/pretty-print-windows-path-variable-how-to-split-on-in-cmd-shell/7940444#7940444

Grüße
rubberman

Content-ID: 234679

Url: https://administrator.de/knowledge/batch-drag-and-drop-files-ampersand-bug-234679.html

Ausgedruckt am: 22.12.2024 um 14:12 Uhr

pieh-ejdsch
pieh-ejdsch 12.04.2014, aktualisiert am 06.10.2019 um 13:46:23 Uhr
Goto Top
moin rubberman,

den Bug kannte ich noch nicht. Ganz schön durchgetüftelte Ersetzung.
Ich habe diese mithilfe der Quotes in der Forschleife gelöst:
@echo off

 rem Anwendung ohne Dateiname
set program= echo Verarbeite

::-------------------------------
set "drag="  
setlocal enabledelayedexpansion
for /f usebackqeol^=^:tokens^=2*delims^=^" %%h in (  
 '!cmdcmdline!'  
) do ( endlocal
 if "%~0" equ "%%h" (  
  set drag="%%i"  
))
if not defined drag exit /b
set /a n=0
call :readDrag
>nul pause|set /p=%n% verarbeitet
exit

:readDrag
if . neq .!! setlocal enabledelayedexpansion
if !drag! equ "" exit /b   

for /f eol^=^:tokens^=1-2*delims^=^" %%h in (!drag!) do (  
 endlocal
 for /f "eol=:tokens=*" %%q in ("%%h") do (  
  set "withoutQ=%%q"  
  if defined withoutQ (
   setlocal enabledelayedexpansion
   for %%f in ("!withoutQ: =" "!") do (if . equ .!! endlocal  
    if %%f neq "" set /a n+=1 & %program% %%f  
 )))
 if "%%i" neq "" set /a n+=1 & %program% "%%i"  
 set   drag="%%j"  
)
goto :readDrag

Gruß Phil
rubberman
rubberman 12.04.2014 um 21:03:28 Uhr
Goto Top
Hallo Phil.

Ganz schön durchgetüftelte Ersetzung.
Die ist im Grundsatz nicht auf meinem Mist gewachsen. Stammt letztlich aus dem letzten Link und ist von mir nur für Leerzeichen angepasst worden. Schade nur, dass man die verzögerte Variablenerweiterung nicht durchgängig nutzen kann. Ich denke, dann könnte man noch etwas mehr herauskitzeln, was die Anzahl (eigentlich die Gesamtlänge) der übergebenen Parameter angeht.

Ich habe diese mithilfe der Quotes in der Forschleife gelöst
Sehr schönes Beispiel, wie man mit Quotes als Delimiter arbeiten kann face-smile
+1

Grüße
rubberman