Ein guter Bekannter meldete sich neulich bei mir, weil er mit einer selbstgestellten Aufgabe nicht weiterkam: Er wollte tausende Fotos, die in diversen Ordnern verstreut lagen, in einen Ordner zusammenkopieren und dabei einfach durchnummerieren. Dabei versuchte er das Problem mit einer klassischen Batchdatei zu lösen. Die stellte sich aber störrisch an, denn die FOR-Schleife, die er dazu einsetzte, zählte einfach die Nummern nicht hoch, sondern vergab immer dieselbe Zahl für den Dateinamen.
for %%b in (c:\ordner\quelle\*.jpg) do ( (set /a zahl+=1) (copy %%b c:\ordner\ziel\%zahl%.jpg) )
Bei Betrachtung der Syntax fand er den Fehler nicht. Der liegt tatsächlich auch eine Ebene tiefer, und die Lösung ist wenig bekannt.
Grundsätzlich leistet die oben aufgeführte FOR-Schleife schon das, was sie soll. Man muss hier allerdings die Eigenheit der Batch-Shell berücksichtigen, Umgebungsvariablen immer in dem Moment aufzulösen, in dem eine Batchzeile erstmals gelesen wird – und nicht dann, wenn sie ausgeführt wird. Das führt dazu, dass die Variable Zahl nur einmal ausgewertet wird, und zwar beim ersten Durchlauf. Danach verwendet die Shell immer denselben Wert, obwohl sie eigentlich angewiesen wurde, den Wert hochzuzählen (was sie im Hintergrund auch tut).
Es gibt aber eine Lösung dafür, und die nennt sich “Delayed Expansion”. Rob van der Voude erläutert dies auf seiner hervorragenden Batch-Seite:
[Batch Files – Variable Expansion in FOR Loops]
http://www.robvanderwoude.com/variableexpansion.php
Hier eine überarbeitete Fassung der FOR-Schleife, eingebettet in ein Beispielskript, das die oben erwähnte Aufgabe löst (mit genau einem Quellordner, hier müsste man also bei Bedarf noch etwas anpassen).
@ECHO OFF REM Aufgabe: REM Kopiere alle Dateien aus Quelle nach Ziel REM und benenne sie dabei fortlaufend numerisch um REM und behalte den Dateityp bei REM Lokale Parameter SET Quelle=C:\Daten\Quelle SET Ziel=C:\Daten\Ziel REM Startwert für die Nummer SET Zahl=1000 REM Wir müssen erst die "Delayed Expansion" einschalten SETLOCAL ENABLEDELAYEDEXPANSION REM Das DIR-Kommando gibt die Dateien in der gewünschten Folge zurück FOR /F "usebackq tokens=*" %%i IN (`DIR %Quelle% /A:-D /B`) DO ( ECHO Alt: %Quelle%\%%i REM "Delayed Expansion" per Notation nutzen: Die Variable, die in jedem Durchlauf REM erweitert werden soll, muss in Ausrufezeichen eingefasst sein SET /A Zahl=!Zahl!+1 REM Um die ursprüngliche Dateierweiterung beizubehalten, hier nochmal REM derselbe Trick, diesmal mit Zeichenfolgen-Funktion (4 letzte Zeichen) SET Zielname=%%i ECHO Neu: %Ziel%\!Zahl!!Zielname:~-4! ECHO. COPY %Quelle%\%%i %Ziel%\!Zahl!!Zielname:~-4! ECHO. )
Und hier der Download des Skripts:
Copy-RenameNumber.bat (767 bytes, 2.901-mal heruntergeladen, letzte Änderung am 24. Februar 2014)
http://faq-o-matic.net/?p=5710