sebastianju
Goto Top

Batch um Dateien nach Anzahl in Ordner abzulegen

Hallo,

ich suche eine Möglichkeit eine Batchdatei in einem Verzeichnis auszuführen in dem eine große Anzahl von kleinen Dateien liegt. Können ein paar Zehntausend sein. Diese Dateien sollen nun alphabetisch nach einer bestimmten Anzahl in Unterordner verpackt werden. Wenn die Anzahl zB 500 wäre dann sollen die ersten 500 Dateien in einen Unterordner der 00500 heißt. Die nachfolgenden in 01000 usw. Pro Datei könnte man das nötige Unterverzeichnis herausfinden indem man zB die Nummer der Datei nimmt die fraglich ist und durch 500 teilt. Davon die Ganzzahl und das wieder mal 500. Dann müsste bei Bedarf nur noch eine Anzahl Nullen davorgesetzt werden damit die Unterordner sortiert sind.

Kann man das mit einer Batch lösen? Ich kenne mich ein wenig damit aus aber nicht so gut um das sagen zu können...

Grüße!
Sebastian

Content-Key: 100196

Url: https://administrator.de/contentid/100196

Printed on: April 20, 2024 at 03:04 o'clock

Member: bastla
bastla Oct 25, 2008 at 06:19:37 (UTC)
Goto Top
Hallo SebastianJu und willkommen im Forum!

Diese Dateien sollen nun alphabetisch ...
... die Nummer der Datei ...
Wenn die Dateien bereits Nummern haben, wozu dann eine alphabetische Ordnung?

Sollte der Dateiname tatsächlich bereits eine laufende Nummer enthalten, wäre es sinnvoll, den Aufbau des Namens darzustellen.

Grüße
bastla
Member: bastla
bastla Oct 25, 2008 at 07:31:23 (UTC)
Goto Top
... unabhängig davon, ob die Nummer erst erzeugt werden muss (davon geht der folgende Ansatz aus) oder bereits vorhanden ist, könnte der Ablauf etwa so aussehen:
@echo off & setlocal
set "Ordner=D:\Ordner mit vielen Dateien"  
set /a Einh=500
set /a Start=1000000000

pushd "%Ordner%"  
set /a ONr=%Start%
set /a Nr=0

for /f "delims=" %%i in ('dir /b /a-d /on') do call :ProcessFile "%%i"  
popd
goto :eof

:ProcessFile
set /a Chk=%Nr%%%%Einh%
if %Chk% neq 0 goto :MoveFile

set /a ONr+=%Einh%
set Akt=%ONr:~-5%
md %Akt%

:MoveFile
move %1 %Akt%
set /a Nr+=1
goto :eof
Die Stellenanzahl (Stichwort: "führende Nullen") für die Ordnernamen ist derzeit auf 5 gesetzt (siehe Zeile 19), kann aber bei Bedarf auf bis zu 9 erhöht werden.

Grüße
bastla

[Edit] Alphabetische Sortierung ergänzt [/Edit]
[Edit2] Fehlendes "%"-Zeichen in Zeile 15 nachgetragen {/Edit2]
Member: Biber
Biber Oct 25, 2008 at 11:22:03 (UTC)
Goto Top
Moin SebastianJu,

willkommen im Forum.
noch eine kleine Fussnote zu bastlas Lösung.

Wenn Du wirklich ein paar 10000 Dateien bearbeiten willst, dann wäre unter Umständen als Zwischenschritt das Schreiben des DIR-Outputs in eine temporäre Datei performanter.

Also statt
..
for /f "delims=" %%i in ('dir /b /a-d /on') do (
...
..lieber der Umweg..
..
dir /b /a-d /on>%temp%\dirlist.txt
for /f "delims=" %%i in (%temp%\dirlist.txt) do (  
..
)
del %temp%\dirlist.txt
...

Okay, wenn der Batch natürlich die einzige gestartete Anwendung ist und sich die Arbeitsspeicher-Ressourcen mit keinen anderen Prozessen teilen muss, dann ist es egal.
Aber im Normalfall soll dieser Batch ja irgendwo im Hintergrund vor sich hin drömeln, während Du im Vordergrund weiterhin ruckelfrei Videoclips geniesst....

Grüße
Biber
Member: SebastianJu
SebastianJu Oct 25, 2008 at 22:36:32 (UTC)
Goto Top
Hallo,

ich habe das erste Skript probiert. Beim zweiten wußte ich nicht wo ich den zweiten Teil reinsetzen soll.

Das Skript arbeitet durch. Erzeugt auch korrekt die Verzeichnisse (Anzahl und Name passt) aber die Dateien werden noch nicht kopiert. Im Zielverzeichnis sind dann halt die Verzeichnisse und die Dateien aber nicht auf die Verzeichnisse verteilt.

Den Code durchschaue ich im Moment noch nicht. Ich werde mir aber mal die Befehle ansehen. Solche Bat-Dateien sind ja immerhin ziemlich nützlich...

Danke für den Code...

Grüße!
Sebastian
Member: Biber
Biber Oct 26, 2008 at 01:36:42 (UTC)
Goto Top
Moin SebastianJu,

bastla ist anscheinend noch inner Disse - deshalb versuche ich mal seine Variante zu kommentieren und auch meine Winz-Änderung einzubauen.
@echo off & setlocal
:: Echo der Befehle auf dem Bildscirm AUS
:: setlocal: alle mit SET gesetzten Variablen gelten nur in diesem Batch

set "Ordner=D:\Ein Ordner mit den vielen Dateien"  
::Hier anpassen: Dein Ordnername

set /a Einh=500
:: Paketgröße...numerische Variable; 500 Dateien je Ordner

set /a Start=1000000000
:: Hilfvariable, die letzten x Zeichen davon bilden den Verzeichnisnamen

pushd "%Ordner%"  
:: Wechseln in das Verzeichnis, in dem die vielen Dateien liegen
:: Und das Verzeichnis merken, von dem Du gestartet bist

set /a ONr=%Start%
set /a Nr=0
:: Zwei weitere numerische Variablen.
:: Was eine 0Nr ist, bekommst Du im Lauf des Lebens alleine raus...*g

dir /b /a-d /on>%temp%\dirlist.txt
:: Komplettinhalt des Verszeichnisses in eine Temp-Datei schreiben

for /f "delims=" %%i in (%temp%\dirlist.txt) do call :ProcessFile "%%i"  
:: Für alle Zeilen in der Temp-Datei jeweils die ganze Zeile 
:: als Parameter %%i für einen Sub-Block :ProcessFile weiterreichen

:: Wenn Du hier ankommst, sind ALLE Zeilen/ALLE Dateien verarbeitet

del  %temp%\dirlist.txt>nul
popd
:: Aufräumarbeiten

goto :eof
:: ~~~Hier ist der Batch zu Ende~~ Unterhalb nur Sub-Routinen

:ProcessFile
set /a Chk=Nr %% Einh
:: Errechne Variable Chk als [Nr modulo Einh]; 
:: Bsp: 777 mod 500=277

if %Chk% neq 0 goto :MoveFile
:: wenn Chk NICHT 0 ist, weiter zu :MoveFile. 

:: Andernfalls sind 500 Dateien im Ordner. 
:: Dann hier weiter.
set /a ONr+=%Einh%
:: die Basis für den nächsten Ordnernamen hochzählen

set Akt=%ONr:~-5%
ECHO md %Akt%
:: Von numerischen Wert die letzten 5 Stellen nehmen und Verzeichnis anlegen.

:MoveFile
ECHO move %1 %Akt%
:: nächste Datei verschieben
set /a Nr+=1
:: ...und den Zähler für die max.500 bzw. max %Einh% um 1 erhöhen.
goto :eof
:: hier bedeutet "goto :eof"-->Ende von :Processfile 

Zusätzlich habe ich vor den beiden eigentlich arbeitenden Befehlen MD und MOVE ein GROSS geschriebenes ECHO gesetzt - so kannst Du den Batch als Simulation durchlaufen lassen und siehst, was passieren würde.

Das müssen wir jetzt einmal tun, um den Fehler bei Dir zu finden.
Poste bitte den Output (bzw. ein paar Zeilen davon).

Grüße
Biber
Member: bastla
bastla Oct 26, 2008 at 08:09:17 (UTC)
Goto Top
@Biber
Danke für die Nachtschicht ... face-smile

... und ja, ich kenne die Passage
Somit können Sie mit Umgebungsvariablen Berechnungen vornehmen, ohne %-Zeichen einzugeben ...
aus der Hilfe zu "set" und hatte auch daran gedacht, diese Kurzform zu verwenden, es aber dann "gut gemeint" (was ja nicht ohne Grund als Gegenteil von "gut gemacht" gilt) und trotzdem die Variablenschreibweise wie gewohnt mit %Variable% vorgenommen.

Dass übrigens %%% anstelle von %% im Batch auch funktionieren kann, ist mir neu - sogar ein
for %%i in (*.txt) do echo %%%i
läuft anstandslos durch ...


@SebastianJu
Jetzt habe ich da oben in Zeile 15 schon so viele "%"-Zeichen verwendet, und dann war's immer noch um eines zu wenig (oder um 3 zuviel face-wink) - ist korrigiert, kann aber nicht der Grund für das "Nicht-Verschieben" gewesen sein, da es sich (weshalb mir beim Testen auch nichts aufgefallen war) nicht weiter ausgewirkt hat (die Verzeichnisse wurden ja auch erstellt).

Mit Bibers Version müsste es aber auf jeden Fall klappen (und wenn Du nach dem erfolgreichen Testen die beiden angesprochenen ECHO entfernst, werden auch tatsächlich Verzeichnisse erstellt und Dateien verschoben).

Grüße
bastla
Member: SebastianJu
SebastianJu Oct 26, 2008 at 14:28:40 (UTC)
Goto Top
Hallo,

danke für die Mühe. Ist schon verständlicher geworden der Code.

Ich habe es jetzt mal durchlaufen lassen. Zur Anzeige habe ich ein "ping -n 300 127.0.0.1 > NUL"
vor dem ersten "goto :eof" eingebaut. Als Ergebnis kommt so etwas heraus:

Für Verzeichniserstellung, die ja klappt:

md 00827 (Bei Zusammenfassung pro 827 Dateien)

Die Aufrufe für das Verschieben sehen dann so aus:

move "Zybex - Cheatcodes - Computer Cheat - Cheat Code - Internet Game Cheats -
PC Cheat - PC Codes - PC Game Codes - PC Games Cheat.url" 16540
move "Zyconix - Cheatcodes - Computer Cheat - Cheat Code - Internet Game Cheats
- PC Cheat - PC Codes - PC Game Codes - PC Games Cheat.url" 16540
move "Zylogon - Cheatcodes - Computer Cheat - Cheat Code - Internet Game Cheats
- PC Cheat - PC Codes - PC Game Codes - PC Games Cheat.url" 16540
move "Zynaps - Cheatcodes - Computer Cheat - Cheat Code - Internet Game Cheats -
PC Cheat - PC Codes - PC Game Codes - PC Games Cheat.url" 16540
move "Zynon - Cheatcodes - Computer Cheat - Cheat Code - Internet Game Cheats -
PC Cheat - PC Codes - PC Game Codes - PC Games Cheat.url" 16540
move "Zyron - Cheatcodes - Computer Cheat - Cheat Code - Internet Game Cheats -
PC Cheat - PC Codes - PC Game Codes - PC Games Cheat.url" 16540
move "Zyrons Escape - Cheatcodes - Computer Cheat - Cheat Code - Internet Game C
heats - PC Cheat - PC Codes - PC Game Codes - PC Games Cheat.url" 16540
move "Zyto - Cheatcodes - Computer Cheat - Cheat Code - Internet Game Cheats - P
C Cheat - PC Codes - PC Game Codes - PC Games Cheat.url" 16540
move "Zytron Mega Blast - Cheatcodes - Computer Cheat - Cheat Code - Internet Ga
me Cheats - PC Cheat - PC Codes - PC Game Codes - PC Games Cheat.url" 16540
move "Zzzzz - Cheatcodes - Computer Cheat - Cheat Code - Internet Game Cheats -
PC Cheat - PC Codes - PC Game Codes - PC Games Cheat.url" 16540

Aber keine Fehlermeldungen. Dann habe ich die Echos entfernt. Im neuen Skript gibt es keine Ausgaben bis auf eine Fehlermeldung die ständig aufkommt(Vorher war viel auf dem Schirm ohne dass man etwas lesen konnte. Trotz Echo off):
"Der Dateiname oder die Erweiterung ist zu lang."

An diese Möglichkeit hatte ich am Anfang ja auch gedacht. Der Pfad in dem die Dateien liegen hat 48 Zeichen und die Dateien nicht mehr als 154 Zeichen. Außerdem werden die Verzeichnisse korrekt erstellt und wenn ich die Dateien von Hand reinkopiere gibt es auch keine Probleme. (Ich kenne die Probleme die auftauchen wenn ein Pfad inklusive Dateiname zu lang ist.)

Könnte das an einer Variablen liegen? Oder kann move keine so langen Pfade bearbeiten?
Die Batch kann ich doch auch ausführen wo ich will da der Pfad ja angegeben wird. Ich führe sie ein Verzeichnis über dem Verzeichnis aus in dem die Dateien liegen. Als Pfad gebe ich einfach nur den Namen des Verzeichnisses an in dem die Dateien liegen...

Grüße!
Sebastian
Member: Biber
Biber Oct 26, 2008 at 18:32:27 (UTC)
Goto Top
Tja SebastianJu,

sieht in der Tat so aus, als hättest Du den bislang undokumentierten M$-Bug No. #138654 gefunden. Eventuell wird der mal nach Dir benannt.

Also, der MOVE-Befehl scheint offensichtliche Probleme mit diesen langen Dateinamen (oder den vielen Leerzeichen im Namen?)" zu haben.

Einfache Verifizierung dieser rufschädigenden Behauptung am CMD-Prompt:
[einzugebende Zeilen beginnen mit ">"]
>set "var=Zybex - Cheatcodes - Computer Cheat - Cheat Code - Internet Game Cheats - PC Cheat - PC Codes - PC Game Codes -PC Games Cheat.txt"
>echo x>"%var%"
>move "%var%" 00500
Der Dateiname oder die Erweiterung ist zu lang.
Anmerkung: der Name der Datei "Zybex -...bla.txt" ist 133 Byte lang und das Verschieben sollte von "D:\temp" nach D:\temp\00500" erfolgen -- also kein erkennbares Limit in der Nähe.

Workaround.
Mach den MOVE-Befehl in zwei Schritten,
Zuerst COPY von A nach B, dann Löschen in A.

Konkret:
STREICHE:
MOVE %1 %Akt%

SETZE:
COPY %1 %Akt%
DEL %1
[Edit] Oder aber (Alternative II):
Oder Du benennst diese etwas sperrigen Dateinamen um
-> von: "Zybex - {endloses sinnfreies Reklamegelumpe}.url
--> in "Zybex.url"
und machst danacht den Schritt MOVE (auch wieder mit dem MOVE-Befehl).
Das ginge durch eine vorgeschaltete REN-Zeile vor der Zeile mit MOVE:
...
FOR %%i in (%1) do FOR /F %%j in ("%%i") do (
         REN %1 %%j%%~xi
         MOVE %%j%%~xi %Akt%
)
REM Dieses FOR-Konstrukt STATT der Zeile "MOVE %1 %Akt%"
...
[/Edit]

Grüße
Biber

Wie teuer is' nochmal dieses Redmonder Standard-Betriebssystem?
Member: SebastianJu
SebastianJu Oct 26, 2008 at 18:51:02 (UTC)
Goto Top
Super. Nach Ersetzen von Move klappt es wunderbar... Dein Beispiel darüber habe ich auch mal nachvollzogen. Der Inhalt der Datei wurde mit einem x ersetzt und auch dann wollte er die Datei nicht verschieben...

Aber so klappt es auch. Ich werde mir vielleicht noch eine Prozentanzeige dazubasteln und die Meldungen über kopierte Dateien ausblenden damit ich noch sehe wie weit es ist...

Vielen Dank!
Sebastian