Top-Themen

AppleEntwicklungHardwareInternetLinuxMicrosoftMultimediaNetzwerkeOff TopicSicherheitSonstige SystemeVirtualisierungWeiterbildungZusammenarbeit

Aktuelle Themen

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit
GELÖST

Batch - mögliche Codeoptimierung?

Frage Entwicklung Batch & Shell

Mitglied: evotoy

evotoy (Level 1) - Jetzt verbinden

16.02.2011, aktualisiert 19:06 Uhr, 3903 Aufrufe, 21 Kommentare

Hi,

ich habe eine kleine Batch geschrieben, die rudimentäre Sortieraufgaben übernimmt. Meine BATCH-Erfahrungen sind leider noch überschaubar.

FRAGE: ist es möglich den folgenden Code so zu optimieren, dass die Batch schneller arbeitet?

01.
@echo off 
02.
 
03.
set "MaskSort=*.jpg 
04.
for /F "delims=" %%i in ('dir/b %MaskSort%') do set "Name=%%~ni" & call :ProcessFile "%%i" 
05.
echo Sortiervorgang beendet.    
06.
goto :eof 
07.
 
08.
:ProcessFile 
09.
 
10.
if exist "%Name:~,-4%" ( 
11.
        move "%name%%~x1" "%Name:~,-4%\" 2>NUL 
12.
    ) ELSE ( 
13.
        echo Erstelle Ordner   : %Name:~,-4%    
14.
        md "%Name:~,-4%" 2>NUL & move "%name%%~x1" "%Name:~,-4%\" 2>NUL 
15.
16.
)
mir is aufgefallen, dass seit ich mit Sprungmarken arbeite die Scripe langsamer laufen als ohne.

Mit Tokens und Delims komm ich der Sache leider nicht bei. Wenn ich die Sprungmarke rausnehme habe ich das Problem, dass in die Variablen in der Schleife nicht gehen. Die Variable brauch ich aber für die Sringmanupulation.
Ich sortiere mit dem Script ca. 10.000 Files - das dauert leider ewig. Der Code hier hat zB. wesentlich schneller gearbeitet:

01.
for /F "tokens=2 delims=-" %%i in ('dir/b') do (  
02.
	if exist "%%~ni" ( 
03.
		move "*%%~ni.*" "%%~ni\" 2>NUL 
04.
	) ELSE ( 
05.
		echo Erstelle Ordner   : %%~dpni    
06.
		md "%%~ni" 2>NUL 
07.
		move "*%%~ni.*" "%%~ni\" 2>NUL 
08.
09.
)
Gibt es eine Möglichkeit den Code von oben so zu optimieren, dass das Script schneller arbeitet? Oder muss man dann direkt auf VBS oder ähnliches umsteigen?

Danke und vg,
Mitglied: Skyemugen
16.02.2011 um 18:46 Uhr
Aloha,

da der Thread schonmal Codeoptimierung heißt, würde ich vorallem die Formatierung im Forum optimieren:
01.
echo mit den passenden tags >>nächste_Zeile
<code></code>

=)

greetz André
Bitte warten ..
Mitglied: evotoy
16.02.2011 um 19:07 Uhr
Besser???

ich hab leider zu selten Zeit zum batchen und ich bindeshalb auch zu selten hier
Bitte warten ..
Mitglied: bastla
16.02.2011 um 19:10 Uhr
Hallo evotoy!

Soferne es keine Namen mit enthaltenen "!" gibt, könntest Du es so versuchen (ungetestet):
01.
@echo off & setlocal enabledelayedexpansion 
02.
 
03.
set "MaskSort=*.jpg 
04.
for /F "delims=" %%i in ('dir/b /a-d %MaskSort%') do ( 
05.
    set "Name=%%~ni" 
06.
    set "Name=!Name:~,-4!" 
07.
    md "!Name!" 2>nul 
08.
    move "%%i" "!Name!\" 
09.
10.
echo Sortiervorgang beendet.
So wird auch nur eine Stringzerlegung (und keine Abfrage ) benötigt.

Grüße
bastla
Bitte warten ..
Mitglied: pieh-ejdsch
16.02.2011 um 19:30 Uhr
moin evotoy,

mir is aufgefallen, dass seit ich mit Sprungmarken arbeite die Scripe langsamer laufen als ohne.
...
Gibt es eine Möglichkeit den Code von oben so zu optimieren, dass das Script schneller arbeitet? Oder muss man dann direkt auf VBS oder ähnliches umsteigen?

schneller als das, was bastla als lösung gepostet hat wirst Du es nicht mehr mit batch bekommen. Das mag daran liegen, das eine Variable (2mal) erst gesetzt wird und auch wieder aufgelöst wird. Das kostet Zeit.
was Du noch überprüfen kannst:
Bei Batches mit Sprungmarken bzw. generell Batches - Ist im Online-Virenscanner die Batch in den Ausnahmen deklariert.

Gruß Phil
Bitte warten ..
Mitglied: Biber
16.02.2011 um 19:50 Uhr
Na ja, pieh-ejdsch,

diese Antwort ist mir zu technisch...
Eine "Optimierung eines Ablaufs" ist doch nicht nur "benutze ich eine oder zwei Stringzerlegungen". Oder ein goto oder verzögerte Variablen.

Bei den oben beschriebenen 10000 zu verteilenden *.jpgs kommt es sicher eher auf die (vorhersagbare) Verteilung in einzelne Ordner an.

Wenn beispielsweise der obige Batch läuft und 10000 Dateien werden in 10000 Ordner verschoben von denen 9999 neu angelegt werden und einer vorher existiert...
Dann ist es die "passende" Lösung.

Wenn allerdings die 10000 Dateien in nur drei Ordner verschoben/verteilt werden sollen, die auch alle vorher existieren...
-> dann würde sicherlich ärgerlich viel Zeit damit verbraten, einfach nur das überflüssige "md "!Name!" 2>nul" abzuwarten.

In dem unterem Szenario wäre es eleganter, nicht die Dateien einzeln abzuklappern, sondern die bestehenden Zielordner.
Und die Dateien auch mit Wildcards en bloc zu verschieben.

Oder drei Parallel-Threads für die drei Ordner loszujagen...


Aber da kann man/frau nur ansetzen, wenn denn dieses Sortierkrams a) regelmäßig und b) mit vorhersagbarer Ausgangssituation stattfindet.

Grüße
Biber
Bitte warten ..
Mitglied: bastla
16.02.2011 um 19:52 Uhr
@PH
Nach einem kurzen Test (mit nur einer Zählschleife mit 30000 Durchläufen und einem "echo" der beiden Befehle) könnte es tatsächlich effizienter sein, nur eine einmalige Variablenzuweisung und dafür die zweimalige Teilstringbildung zu verwenden - als Schleifeninhalt daher:
01.
    set "Name=%%~ni" 
02.
    md "!Name:~,-4!" 2>nul 
03.
    move "%%i" "!Name:~,-4!\"
Der Unterschied lag bei etwa 5 % ...

Grüße
bastla

[Edit] @Biber
"Optimierung eines Ablaufs"
wäre dann vermutlich das Thema des nächsten Threads geworden ...
[/Edit]
Bitte warten ..
Mitglied: pieh-ejdsch
16.02.2011 um 20:27 Uhr
diese Antwort ist mir zu technisch...
wohl eher auch noch zu Allgemein gehalten.
In dem unterem Szenario wäre es eleganter, nicht die Dateien einzeln abzuklappern, sondern die bestehenenden Zielordner.
Und die Dateien auch mit Wildcards en bloc zu verschieben.
das wäre dann die Option für den ersten Teil des Scriptes, damit im zweiten Teil nicht soviel ["md Ordner" aber ohne Fehlermeldung] durchgeführt werden.

@bastla hast Du Die Ausgabe Weggeleitet?

da das Auflösen einer Variable etwas länger dauert als das setzen - dürfte, wenn ich mit meiner Theorie nicht falsch liege, die mindest-zweimalige Auflösung dieser Variable als Laufvariable noch einen Zacken schneller sein als das Direkte Auflösen der Variable.

ist ein "if not exist Ordner md Ordner" nicht schneller als ein "md Ordner 2>nul"

Gruß Phil
Bitte warten ..
Mitglied: jeb-the-batcher
16.02.2011 um 21:16 Uhr
Zitat von bastla:
Hallo evotoy!

Soferne es keine Namen mit enthaltenen "!" gibt, könntest Du es so versuchen (ungetestet):

Damit es auch mit dem bösen "!" klappt, kann man einfach den Block noch ein bisschen mit Setlocal und Endlocal würzen.

01.
@echo off 
02.
setlocal DisableDelayedExpansion 
03.
 
04.
set "MaskSort=*.jpg 
05.
for /F "tokens=* delims=" %%i in ('dir/b /a-d %MaskSort%') do ( 
06.
    set "Name=%%~ni" 
07.
    set "OrgName=%%~ni" 
08.
    setlocal EnableDelayedExpansion 
09.
    set "Name=!Name:~,-4!" 
10.
    md "!Name!"  
11.
    move "!OrgName!" "!Name!\" 
12.
    EndLocal 
13.
) 2>nul 
14.
echo Sortiervorgang beendet.
Und die Kombination "Tokens=* delims=" entspricht von der Ausgabe "delims=" ist aber schneller (abhängig von den Stringlängen).

Gruß
jeb
Bitte warten ..
Mitglied: bastla
16.02.2011 um 21:21 Uhr
@jeb
Damit es auch mit dem bösen "!" klappt, kann man einfach den Block noch ein bisschen mit Setlocal und Endlocal würzen.
Das ist schon klar, aber nicht Im Sinne der Optimierung (wenn eben "!" auszuschließen sind) ...

Grüße
bastla
Bitte warten ..
Mitglied: pieh-ejdsch
16.02.2011 um 21:39 Uhr
moin jeb,

Und die Kombination "Tokens=* delims=" entspricht von der Ausgabe "delims=" ist aber schneller (abhängig von den Stringlängen).
wie meinst Du abhängig?
bei beiden oder nur bei "delims=" ?
versucht die Forschleife etwa erst den ganzen Sting in viele Tokens (welche ja nur eines sind) zu zerlegen und dann werden diese wieder zusammengesetzt?
sonst müsste es ja keinen messbaren Unterschied geben.

Gruß Phil
Bitte warten ..
Mitglied: Biber
16.02.2011 um 22:14 Uhr
Wenn wir hier ohnehin alle durcheinander rumirrlichtern, ohne den TO abzuwarten...
... einen habe ich auch noch...

for /l %%a in (1,1,30000) do if not exist R:\bla md R:\bla 1003 ms
for /l %%a in (1,1,30000) do md R:\bla 2>nul 4445 ms

Wozu denn jetzt blind irgendwelche Perlen/Ausrufezeichen/in Tränen aufgelösten Variablen in die Nacht/vor die Säue/durchs Dorf werfen/treiben?

Menno, früher haben wir die Menschen darauf hingewiesen, dass Bätche sogar unbeaufsichtigt laufen können, wenn sie sauber geschrotet sind.

Who cares denn, ob das Verschieben von 10000 Dateien 10 Minuten oder 45 Minuten dauert?
Wenn ich den Windows-Explorer damit losjage und der mir seine fliegenden Datenklumpen hinmalt, dann dauert es prognostiziert zwischen 45 und 7865 Minuten und er ist je nach Laune zu 3% ich korrigiere 44% ich korrigiere 9% ich korrigiere 144% fertig...

5 % Laufzeitoptimierung bei einem Batch.... dafür steh ich nicht nachts auf...

Grüße
Biber
Bitte warten ..
Mitglied: jeb-the-batcher
16.02.2011 um 23:41 Uhr
Zitat von Biber:
Wenn ich den Windows-Explorer damit losjage und der mir seine fliegenden Datenklumpen hinmalt, dann dauert es prognostiziert
zwischen 45 und 7865 Minuten und er ist je nach Laune zu 3% ich korrigiere 44% ich korrigiere 9% ich korrigiere 144% fertig...

5 % Laufzeitoptimierung bei einem Batch.... dafür steh ich nicht nachts auf...

Wie recht er hat!

tokens=* ist schneller als delims=, macht aber nunmal auch was anderes, schluckt so nebenbei am Anfang alle Spaces und Tabs.
Zusammen sind sie stark und schnell.
Allerdings nur wenn die Daten auch lang sind, bei kurzen Strings oder hier dem Dateiname, geht der Unterschied so ziemlich gegen 0,0%.

Bei langen Strings wird es dann aber immer größer, so emotional gefühlte 50%-200%. (Ab 1000Zeichen ++).
Vermutlich hier nicht ganz so relevant, ausser die Dateinamen wären überraschend lang.

Das Verschieben der Dateien dürfte allerdings bereits beendet sein, während hier noch über die schnellste Lösung debattiert wird.

Grüße
jeb
Bitte warten ..
Mitglied: evotoy
17.02.2011 um 00:10 Uhr
wow ... danke für die vielen Posts ... bis ich da durch bin brauch ich aber n bisschen ... bin schon gespannt was da noch so geht! Probier das morgen gleich mal aus ...

bis denne
Bitte warten ..
Mitglied: evotoy
17.02.2011 um 00:56 Uhr
ich nochmal ... hab jetzt alle Posts durch - möchte aber nicht behaupten, dass ich da komplett mitkomme. Ich hab mir doch nochmal den Spaß gemacht die Files im Explorer auzulesen - das mach ich nie wieder!! muss die Zahl etwas noch oben korrigieren. Sind nicht 10.000 sondern 100.000+ Files (nach dem Sortieren ca 50 Ordner mit je 2000Files) ????? Da sollte ich mir generell was anderes einfallen lassen ;) aber ich will ja meine basic Batch skills verbessern und es wurmt mich halt selber tierisch, dass ichs nicht schneller hinbekomme! ... auf jeden Fall macht das schon nen krassen Unterschied ob man 40 Min vorm Rechner sitzt und wartet oder 5 ... erst recht wenn der Feierabend entsprechend nach hinten rückt ... 5% sind bei 5 Min dann nicht mehr so relevant aber die 40 sind definitiv nicht so cool und das ist der aktuelle Stand.

Ich teste das auf jeden Fall mal das Script von Bastla und dann versuch ich mal das von jtbatcher zu schnallen. Das Script von Bastla hatte ich heut schonmal fast so - allerdings ohne die "!" - ging natürlich nicht - was muss man denn da googeln wenn man zu !Name! was finden will? Ich hab dazu schonmal was gelesen - hab aber keine Idee nach was ich da eigentlich suchen soll (?????Variable). Das Script läuft damit aber bestimmt schonmal ne ganze Ecke schneller als meins und die Sequenzen als Blöcke zu verschieben könnte auch nochmal extremst was bringen. Damit könnte man 2000 Files mit einem Durchlauf abfrühstücken ...

bis nach dem Test

grüße
Bitte warten ..
Mitglied: bastla
17.02.2011 um 08:44 Uhr
Hallo evotoy!

Vermutlich wird's dann die Kombination bringen - etwa:
01.
@echo off & setlocal 
02.
set "MaskSort=*.jpg" 
03.
for /d %%i in (*) do move "%%i%MaskSort%" "%%i" 
04.
for /F "tokens=* delims=" %%i in ('dir/b /a-d %MaskSort%') do ( 
05.
    set "Name=%%~ni" 
06.
    set "OrgName=%%~ni" 
07.
    setlocal EnableDelayedExpansion 
08.
    set "Name=!Name:~,-4!" 
09.
    if not exist "!Name!" md "!Name!"  
10.
    move "!OrgName!" "!Name!\" 
11.
    endlocal 
12.
13.
echo Sortiervorgang beendet.
[Edit] Überzähligen "*" aus "move"-Quelle entfernt [/Edit]
Dein gesuchtes Suchwort ist übrigens "delayedExpansion" ...

Grüße
bastla
Bitte warten ..
Mitglied: Biber
17.02.2011 um 08:49 Uhr
@bastla
Muss es in Zeile 3 nicht statt "...move "%%i*%MaskSort%" besser lauten "...move "%%i\%MaskSort%" ?
Nein, Unsinn...
Wenn schon, dann
01.
 ... 
02.
Set "SortMask=.jpg" 
03.
for /d %%i in (*) do @echo move "*%%i%Sortmask%" "%%i\" 
04.
...
Beispiel:
>for /d %i in (*) do @echo move "*%i.jpg" "%i\" 
move "*logs.jpg" "logs\"
Grüße
Biber
Bitte warten ..
Mitglied: bastla
17.02.2011 um 08:57 Uhr
@Biber
Da aus dem aktuellen Ordner in dessen entsprechende Unterordner verschoben werden soll, sollte das so schon passen - Beispiel: In den Unterordner "Bilder105" sollten alle "Bilder105????.jpg" verschoben werden (wobei die Schreibweise mit "*" zugegeben etwas weniger genau ist) ...

[Edit] Da "*" ja schon in %Maskort% enthalten ist, ginge es ja auch gar nicht mit "????" - allerdings kann er dann auch in der Quellangabe eingespart werden [/Edit]

Grüße
bastla
Bitte warten ..
Mitglied: pieh-ejdsch
17.02.2011 um 09:02 Uhr
moin,

noch ne andere Strategie mit Liste (ungetestet)
01.
::----snipp----MoveTo0,-4Folder.cmd 
02.
@echo Off 
03.
set Woher="D:\ein Verzeichnis" 
04.
set "MaskSort=*.jpg" 
05.
pushD %Woher% 
06.
if exist "%temp%\Dirtmp2" del  "%temp%\Dirtmp2" 
07.
:Anfang 
08.
if exist "%temp%\Dirtmp" del "%temp%\Dirtmp" 
09.
if exist "%temp%\Dirtmp2" (move "%temp%\Dirtmp2" "%temp%\Dirtmp">nul ) else dir /b %MaskSort%>"%temp%\Dirtmp"||(popD&goto :eof) 
10.
set /p Name=<"%temp%\Dirtmp" 
11.
if not exist "%Name:~,-4%" md "%Name:~,-4%" 
12.
move "%Name:~,-4%????%MaskSort:~-4%" "Name:~,-4%" 
13.
findstr /i /v /b "%Name:~,-4%....%Masksort:~-4%" "%temp%\Dirtmp">"%temp%\Dirtmp2" 
14.
goto :Anfang 
15.
::----snapp----MoveTo0,-4Folder.cmd
[Edit] beim DEL "2>nul" entfernt und stattdessen if exist eingefügt
findstr Suchzeichenfolge nochmal angepasst
beim MOVE 4 Platzhalter eingesetzt statt ein Stern (sonst gehts in die Hose bei mehreren Namenlängen und gleichen anfang
[/Edit]


Gruß Phil
Bitte warten ..
Mitglied: Biber
17.02.2011 um 09:06 Uhr
Sorry. bastla,

ich nehme alles zurück...
Ich habe die Namens-Abschneidekonvention falsch gelesen - es bleibt ja der Namens-Anfang erhalten.
Ich sollte niemals vor dem Morgenkaffee posten...

Grüße
Biber
Bitte warten ..
Mitglied: evotoy
19.02.2011 um 22:59 Uhr
Hi,

sorry dass ich mich die letzten Tage nicht melden konnte ... ich hab die Scripte alle durchgetestet. Musste allerdings feststellen, dass wirkliche Laufzeiten zu messen kaum machbar ist. Bei den Datenmengen kommt selbst der Explorer permanent ins Straucheln - selbst das Umbenennen eines Ordners dauert ca 7 Sekunden. Die Scripte funktionieren alle super!! Ich hab auf jeden Fall wieder was dazu gelernt ;) Schlussendlich hab ich jetzt den Source verwendet:

01.
 
02.
@echo off & setlocal enabledelayedexpansion 
03.
set "vorher=%time%" 
04.
 
05.
set "MaskSort=*.tif 
06.
for /F "tokens=* delims=" %%i in ('dir/b /a-d %MaskSort%') do ( 
07.
    set "Name=%%~ni" 
08.
    setlocal EnableDelayedExpansion 
09.
    set "Name=!Name:~,-4!" 
10.
	if not exist "!Name!" md "!Name!" 
11.
    move /y "!Name!*.*" "!Name!\" 
12.
    EndLocal 
13.
) 2>nul 
14.
echo Sortiervorgang beendet. 
15.
set "danach=%time%" 
16.
echo Laufzeit = %vorher% - %danach% 
17.
pause 
18.
 
Beim ersten Testdurchlauf war das Script von den fünf Varianten das Schnellste - aber die Aussage ist nur bedingt aussagekräftig. Beim zweiten Durchlauf kamen ganz andere Ergebnisse raus und die Scripte haben auch ab und an mal "gehangen" - schätze, dass meine lokalen Festplatten da gar nicht nicht mitkommen -120000 Files a 20kb-1,5MB - da sind die Köppe ganz schön unterwegs.

Also um da ne wirkliche Aussage zu treffen bräucht ich wohl n neu aufgesetztes RAID ...

Die Variante mit der Liste werde ich mir bei Gelegenheit auch noch einmal zu Gemüte führen - Vielen Dank für die Hilfe!
Bitte warten ..
Mitglied: bastla
19.02.2011 um 23:57 Uhr
Hallo evotoy!

Letzter Optimierungsvorschlag: In einem Batch braucht "move" kein "/y" ...

Grüße
bastla
Bitte warten ..
Neuester Wissensbeitrag
Humor (lol)

Linkliste für Adventskalender

(3)

Information von nikoatit zum Thema Humor (lol) ...

Ähnliche Inhalte
Batch & Shell
Dateinamen nach Zeichnen abschneiden - Batch-Shell (9)

Frage von cberndt zum Thema Batch & Shell ...

Batch & Shell
CMD Verschlüsslung ( Batch ) (9)

Frage von clragon zum Thema Batch & Shell ...

Batch & Shell
gelöst älteste dateien via batch löschen (6)

Frage von cali169 zum Thema Batch & Shell ...

Batch & Shell
gelöst Suchen und Ersetzen mehrerer Suchbegriffe per Batch (4)

Frage von makroll10 zum Thema Batch & Shell ...

Heiß diskutierte Inhalte
Exchange Server
gelöst Exchange 2010 Berechtigungen wiederherstellen (20)

Frage von semperf1delis zum Thema Exchange Server ...

Windows Server
DHCP Server switchen (20)

Frage von M.Marz zum Thema Windows Server ...

Hardware
gelöst Negative Erfahrungen LAN-Karten (19)

Frage von MegaGiga zum Thema Hardware ...

Exchange Server
DNS Einstellung - zwei feste IPs für Mailserver (15)

Frage von ivan0s zum Thema Exchange Server ...