Batch-Renamer für Verzeichnisstruktur

Hallo liebe Experten,

ich kenne mich leider nicht so gut mit batch-Dateien aus, deshalb brauche ich eure Hilfe.
Und zwar bräuchte ich eine Batch-Datei, die Folgendes macht:
Ab dem Ordner, wo sie sich befindet, eine komplette Verzeichnisstruktur durchsuchen und jede Datei, die sie findet

  • umbenennen in Pfad (getrennt mit ~ statt )~Dateiname
  • verschieben in das root-Verzeichnis (dort, wo sich die Batchdatei befindet)
    Kann mir jemand dabei helfen? Das wäre super!
    Danke für eure Antworten!

Gruß Timo

Hi …

Hallo liebe Experten,

ich kenne mich leider nicht so gut mit batch-Dateien aus,
deshalb brauche ich eure Hilfe.

Ok …

Und zwar bräuchte ich eine Batch-Datei, die Folgendes macht:
Ab dem Ordner, wo sie sich befindet, eine komplette
Verzeichnisstruktur durchsuchen und jede Datei, die sie findet

  • umbenennen in Pfad (getrennt mit ~ statt )~Dateiname
  • verschieben in das root-Verzeichnis (dort, wo sich die
    Batchdatei befindet)
    Kann mir jemand dabei helfen? Das wäre super!

Bevor ich mich an die Arbeit mache, folgende Rückfrage:

Dir ist klar, dass es unter Windows eine maximale Dateinamenslänge von (ca.) 250 Zeichen gibt? Wenn Du jetzt schon ohnehin lange Dateinamen hättest, z.B. Musik-mp3s die Album- Künster- und Titelnamen beinhalten, und die in Verzeichnisse gestaffelt sind in denen z.B. Albumname und Jahreszahl vercodiert sind, ist es nicht unwahrscheinlich, dass zumindest einige Dateien die maximale Pfadlänge sprengen werden. Eine Batch fliegt bei sowas gnadenlos auf den Bauch.

Weiters würde es wohl zum guten Ton gehören, die (möglicherweise) leeren Unterverzeichnisse, die beim einfachen raus-reneman aller enthaltenen Dateien stehen bleiben würden, zu entfernen. Das klinbgt einfach, aber dabei kommt es regelmäßig zu Krieg gegen Windows, z.B. wegen fehlender Recht, liegengebliebener Thumbs.db Dateien und anderem Mist, und nur mit einer Batch als Bordbewaffnung sind einem da schnell die Hände gebunden, bzw. ufert der Aufwand ins Absurde aus. Man codiert sowas - je nach Windows Version - besser mit WSH oder mit Powershell. Das löst zwar das Problem nicht grundsätzlich, aber man kann programmtechnisch vernünftig auf die Probleme reagieren.

Wenn Du sagst, dass das beides ausgeschlossen ist, bzw. dass Dich das nicht stört, mache ich mich gleich an die Arbeit.

Danke für eure Antworten!

Gruss Armin.

Hallo Nihil,

Nimral vermutet, dass du in einer Windows-Umgebung unterwegs bist, vermutlich weil du nach einer Batch-Datei fragst. Da mir allerdings in Windows-Umgebungen eher selten der Begriff Root-Verzeichnis untergekommen ist, bin ich mir nicht sicher. Erzähl uns doch mal, mit welchem Betriebssystem du überhaupt arbeitest, das wäre mit Sicherheit kein Fehler :wink:

LG
Petra

Hallo und Danke für die Antwort!
Problematisch wird es natürlich, wenn man die Datei innerhalb des Unterverzeichnisses umbenennt - in der Batch-Datei könnte man ja aber auch verlangen, dass er sie erst ins Stammverzeichnis verschiebt und dann umbenennt, richtig?
Ansonsten… ausgeschlossen ist das natürlich nicht. :wink: Könnte man da nicht noch einen kleinen Test einbauen, der einem sagt, dass das nicht geht und überspringt?
Leere Verzeichnisse müssen nicht unbedingt gelöscht werden, das kann ich dann auch manuell per Explorer++, da seh ich dann auch, wenn noch Dateien übriggeblieben sind, deren Namen zu lange waren.

Hi! Die Vermutung war richtig - ich bin nur zu 99% in englischen Foren unterwegs, da red ich öfters mal von den englischen Begriffen. :wink:

Die Frage ist letztlich auch, ob das mit einem einfachen Java-Programm nicht sogar besser geht - ich will deine Kompetenz nicht bezweifeln, ich weiß nur, dass manche komplizierten Sachen in anderen Sprachen einfacher sind. :wink:

Hi …

Die Frage ist letztlich auch, ob das mit einem einfachen
Java-Programm nicht sogar besser geht - ich will deine
Kompetenz nicht bezweifeln, ich weiß nur, dass manche
komplizierten Sachen in anderen Sprachen einfacher sind. :wink:

Im vorliebenden Fall heißt der Entscheidungsbaum „Batch oder was Anderes“. Alles Andere als Batch ist programmiertechnisch besser, inclusice Visual Basic for Applications (gemeinhin als „Word/Excel/Office Makro“ bezeichnet). Die alte DOS Batch Sprache ist (und war immer schon) zum Programmieren derart jenseits aller Vernunft dass man sie wirklich nur für allersimpelste Aufgaben brauchen kann.

Nur ein Detail ist natürlich da, das für die Batch spricht: Du brauchst - anders als z.B. bei Java - keine Runtimes herunterzuladen und zu installieren. Wenn man diesen kleinen Vorteil nicht verschenken (oder wegdiskutieren) will, braucht man eine Programmiersprache, die in Windows bereits eingebaut ist, und landet man bei WSH (geht überall - mein Favorit), oder meinetwegen auch Powershell (Voraussetzung Windows 7 - ist grad angesagt, warum auch immer, und Powershell vorzuschlagen ist sozusagen „en vogue“).

Du sprichst z.B. in Deiner anderen Antwort von einem „kleinen Check“, viel Spaß beim Feststellen einer Stringlänge mit einer Batch :smile:

Ich bleibe daher dabei: wenns ein blitzdummer, blinder AUtomat sein darf, dann machen wir das mit Batch. Wenns ein wenig intelligent werden soll, mit WSH, und wenn Du unbedingt drauf stehst (und ein passendes Windows hast): Powershell.

Und was die Pfadlänge betrifft: der Dateinamen verlängert sich um die Pfadnamen, Letztendlich ist das - weil die „böse“ Dateinamenslänge von knapp 250 die Pfadnamen ebenfalls mitzählt - ein nullsummenspiel, c:\Verz1\blabber.mp3 ist genau gleich lang c:~Verz1~blabber.mp3. Warum es dennoch wichtig ist? Microsoft hatte in allen Windows Versionen diverse Bugs im Diensten und Programmen, die es erlaubt haben, Dateinamen anzulegen, deren Pfadlänge die 250 Zeichen überschreitet. Die Batch würde über solche Dateien stolpern.

In unserer Batch - wenn ich Dich richtig verstanden habe, sollen die fertigen Dateinamen den ehemaligen Pfad (die Unterverzeichnisnamen) komplett beinhalten, oder wolltest Du nur das letzte Verzeichnis im Pfad, also das wo die Datei drinnen lag, im Dateinamen haben?

c:\vertz1\verz2\gnaddel.mp3 --> c:~verz1~verz2~gnaddel.mp3

oder

c:\vertz1\verz2\gnaddel.mp3 --> ~verz1~verz2~gnaddel.mp3

oder

c:\vertz1\verz2\gnaddel.mp3 --> verz2~gnaddel.mp3

… was solls sein? Schick eventuell mal ein paar eigene Beispiele.

Gruss Armin.

Hi!
Danke für die ausführlichen Erklärungen! :smile: Machen wir das doch mal mit Batch. :wink:
Zu den Beispielen: nicht ganz. Hier was ich meine

Die Batch-Datei liegt im Verzeichnis „C:\dings\bums“ (wichtig).

Darin liegen Dateien in Unterordnern, sowas wie
„C:\dings\bums\hallo\welt.mp3“ und
„C:\dings\bums\hallo\armin!.mp3“

Daraus wird:
„C:\dings\bums\hallo~welt.mp3“ und
„C:\dings\bums\hallo~armin~!.mp3“

Wird die Batch jetzt im Ordner C:\dings ausgeführt, dann sind die Resultate
„C:\dings\bums~hallo~welt.mp3“ und
„C:\dings\bums~hallo~armin~!.mp3“

Ich brauch die Dateien dringend da, wo ich die Batch-Datei ausführe, sonst wird der Vorgang extrem unübersichtlich. Ist das machbar?

Hi …

so viele Sternchen kannst Du mir gar nicht geben :smile: Also hier mal mein erster Wurf für „renfiles.bat“. Ich habe die Routine mit ein paar Testdaten gefüttert und getestet, aber die Anwendung des Programms erfolgt dennoch auf eigene Gefahr, ich hafte nicht für Datenschäden, und empfehle erst einmal den DRYRUN (siehe unten) auszuführen, aber selbst der garantiert nicht 100% für fehlerfreie Ausführung! (In einer Zeit wo sich mehr Anwälte um EDV kümmern als EDV-ler muss ich das so schreiben).

@if "%DEBUG%"=="" Echo off

Set FileSpec=\*.mp3

Rem Kommandozeilenparameter übernehmen
Set \_Source=%1

Rem Kommandozeilenhilfe (/?)
if "%\_Source%"=="/?" Goto DisplayHelp
if "%\_Source%"=="?" Goto DisplayHelp

Rem ggf. Hochkomma entfernen
Set Source=%Source:"=%

Rem Wenn Source nicht angegeben, aktuelles Verzeichnis nehmen
If "%\_Source%"=="" Set \_Source=%CD%

Echo renfiles.bat V0.1 (C)2014 by Nimral
Echo ------------------------------------------------------------------
Echo.
Echo Quellverzeichnis: %\_Source%\%FileSpec%
Echo.
Echo Druecke Strg-C fuer Abbruch, Eingabetaste fuer los gehts.
Pause



> Losgehts


 REM Trailing Backslashes entfernen
 If "%\_Source:~-1"=="\" Set \_Source=%\_Source:~0,-1%

 REM Verzeichnisse prüfen
 If not Exist "%\_Source%\." Goto :Error "Fehler: Quellverzeichnis %\_SOurce% nicht gefunden!"

 REM und jetzt gehts los ...
 For /F "tokens=\*" %%d in ('dir %\_Source% /A:d /B') do Call :stuck\_out\_tongue:rocessTree "%\_Source%\%%d" "%%d"


Goto Finish



> ProcessTree

 Set \_Directoryname=%1
 Set \_Directoryname=%\_Directoryname:"=%
 Set \_Prefix=%2
 Set \_Prefix=%\_Prefix:"=%
 Echo ProcessTree: %\_DirectoryName%

 Rem die Dateien beackern
 if Exist %\_DirectoryName%\%FileSpec% For /F "tokens=\*" %%f in ('dir %\_DirectoryName%\%FileSpec% /A:-d /B') do Call :Rename1File "%\_Directoryname%\%%f" "%\_Source%\%\_Prefix%~%%f"

 Rem Rekursion in die Unterverzeichnisse
 For /F "tokens=\*" %%d in ('dir %\_DirectoryName% /A:d /B') do Call :stuck\_out\_tongue:rocessTree "%\_DirectoryName%\%%d" "%\_Prefix%~%%d"
 Goto :EOF



> Rename1File

 Set \_SourceFileName=%1
 Set \_SourceFileName=%\_SourceFileName:"=%
 Set \_TargetFileName=%2
 Set \_TargetFileName=%\_TargetFileName:"=%
 Echo %\_SourceFileName% -- %\_TargetFileName%
 If "%DRYRUN%"=="" move "%\_SourceFileName%" "%\_TargetFileName%"
 goto :EOF



> Error

 Echo.
 Echo Programmabbruch wegen eines furchtbar schweren Fehlers
 Echo.
 Set \_Error=%1
 Set \_Error=%\_Error:"=%
 Echo %\_Error%
 Echo.
 Pause
 Goto Finish




> DisplayHelp

 REM Kommandozeilenhilfe (/?)
 Echo.
 Echo Aufrufparameter
 Echo --------------
 Echo renfiles ["Zielverzeichnis"]
 Echo.
 Echo Anmerkungen:
 Echo ------------
 Echo "" koennen weggelassen werden, wenn kein Leerzeichen im Verzeichnisnamen vorkommt
 Echo Default fuer Zielverzeichnis ist das aktuelle Verzeichnis
 echo.
 Pause
Goto Finish




> Finish

 Echo Programmende.

Noch schnell zwei Überlebenswichtige Hinweise:

  • zum Testen startest Du das Programm am besten von einer Kommandozeile aus.
  • renfiles /? gibt Hilfe aus
  • Set DEBUG=1 schaltet zeilenweise Ausgabe aller Batch befehle ein
  • Set DEBUG= schaltet das wieder aus
  • Set DRYRUN=1 schaltet einen Modus ein, wo nix wirklich verschoben wird
  • Set DRYRUN= schaltet das wieder aus

Meine dringende EMpfehlung: Set DRYRUN=1, Programm laufen lassen, Bildschirmausgaben misstrauisch beäugen, wenns passt, Set DRYRUN=0, kurzes Stoßgebet, und dann los. Denn ein Rückgängig ist nicht, insofern würde ich sogar hergehen und ein Backup von den ursprünglichen Dateien anlegen, nur für den Fall. Wenn die Batch mal 1000 Dateien erfolgreich beackert hat, kann man mutiger werden, und den DRYRUN und das Backup weglassen. Denn den Endtest überlasse ich - auch angesichts der Uhrzeit - Dir.

Solltest Du Fragen zum Code haben, den die REMs nicht beantworten, dann frag. Sollte die Batch nicht laufen, etwa weil das www Forum irgendwelche Sonderzeichen verschluckt hat --> sende mir eine private Nachricht mit einer E-Mail Adresse, und ich sende Dir die Batch als Datei.

Gruss Armin.

Ersteinmal VIELEN DANK für die unglaubliche Mühe, die du dir gemacht hast!!!
Ich hab den Suchparameter erstmal auf *.* gesetzt, weil ich alle Dateien haben will, dann die Zeile Set DEBUG=1 eingefügt am Anfang, laufen lassen und… eine Fehlermeldung bekommen. Hier ist ein Link zum Screenshot: https://imageshack.com/i/ipuP7cfpp

Hi …

Hm, wenn Du Dir diesen elenden Salat auf dem Bildschirm anschaust beschleicht Dich nicht irgendwo das leise Gefühl, dass eine halbwegs ordentliche Programmiersprache auch die Fehlersuche wesentlich erleichtern würde?

Aber ich will nicht jammern. Ärmel hoch, Kotztüten bereit (Batches debuggen ohne die Maschine zur Verfügung zu haben … ich muss verrückt sein …).

Aber gut. Wenn ich das richtig sehe, startest Du das Programm in einem Verzeichnis i:!vgm temp…\test. Die Meldung weist ein wenig darauf hin, dass sich **unterhalb** dieses Verzeichnisses nichts mehr befindet? Und Du hast, wenn ich das richtig interpretiere, DEBUG=1 direkt in die Datei geschrieben, statt den Set Befehl zu verwenden? Und das mit dem DRYRUN erst mal ignoriert? Das ist an sich kein Problem, sind ja eine Daten, sagt mir aber auch, dass Du möglicherweise die Datei nicht aus einer Kommandozeile startest, sondern per Doppelklick aus dem Explorer heraus?

Gruss Armin

Hi!

Hab mal „Set DRYRUN=1“ zugefügt, dann stehen in der Liste die korrekten Dateinamen. Lass ich’s weg, dann macht er exakt das Gleiche, ohne was umzubenennen. :-\
Die Batch starte ich aus der Kommandozeile. Irgendeine Idee? Hoffe mal, dass das nichts mit Windows 8 zu tun hat - nicht dass die da irgendwas geändert haben…

Gruß Timo

Windows 8? Das auch noch. Das sagt er mir jetzt … Ächz. Ist für Windows 8 nicht Toys 'r us zuständig?

Irgendwo müsste ich noch irgendwo ein Windows 8 als virtuelle Maschine rumfliegen haben … mal sehen ob ich Deine Umgebung nachbauen kann.

Inzwischen könntest Du mir auch noch eine Idee geben, wie die Dateien auf Deiner Platte strukturiert sind, damit ich meine Tests besser machen kann. Am liebsten wäre mir, Du führst im Verzeichnis, wo Du die umbenannten Dateien haben möchtest, einen Befehl aus:

dir /s >inhalt.txt

und schickst mir die Datei inhalt.txt als E-Mail, meine E-Mail Adresse habe ich Dir als PM geschickt.

Gruss Armin.

Ist geschickt.

Hi allseits,

wie per PM mit nihil besprochen poste ich hier das Endresultat der gemeinsamen Bemühungen, damit die Community auch was davon hat.

Die Batch macht was verlangt wurde (Achtung: filespec ist jetzt *,.*, nicht mehr *.mp3), und wurde unter Windows 8 getestet. Ich mache mir aus Zeitgründen nicht die Mühe herauszufinden, warum genau die erste Version der Batch unter Windows 7 nicht auf Anhieb lief, und da ich es nicht lassen konnte, an der einen doer anderen Stelle noch eine kleine Verhübschung einzubauen kann ich nicht mehr genau sagen, welche Änderung genau den Durchbruch brachte. Möglicherweise bracht auch das Übermitteln der Batch per Mail statt hier über das Foum den Durchbruch - Batches werden wegen ihrer Sonderzeichen von Webobderflächen manchmal nur verstümmelt wiedergegeben.

Hier also der fertige Code.

@if „%DEBUG%“=="" Echo off
Set FileSpec=*.*

Rem Kommandozeilenparameter übernehmen
Set _Source=%1

Rem Kommandozeilenhilfe (/?)
if „%_Source%“=="/?" Goto DisplayHelp
if „%_Source%“=="?" Goto DisplayHelp

Rem Wenn Source nicht angegeben, aktuelles Verzeichnis nehmen
If „%_Source%“=="" Set _Source=%CD%
Rem ggf. Hochkomma entfernen
Set _Source=%_Source:"=%
Rem ggf. trailing Backslash entfernen
Set _Test=%_Source:~-1%
If „%_Test%“=="" Set _Source=%_Source:~0,-1%

Hello

Rem Benutzer gebuehrend begruessen
Echo -----------------------------------
Echo renfiles.bat V0.2 ©2014 by Nimral
Echo -----------------------------------
Echo.
Echo Mein Verzeichnis: %CD%
Echo Quellverzeichnis: %_Source%%FileSpec%
Echo.
Echo Druecke Strg-C fuer Abbruch, Eingabetaste fuer los gehts.
Echo.
Pause

Losgehts

REM Trailing Backslashes entfernen
If „%_Source:~-1“=="" Set _Source=%_Source:~0,-1%
REM Verzeichnisse prüfen
If not Exist „%_Source%.“ Goto :Error „Fehler: Quellverzeichnis %_Source% nicht gefunden!“
REM und jetzt gehts los …
For /F „tokens=*“ %%d in (‚dir %_Source% /A:d /B‘) do Call :stuck_out_tongue:rocessTree „%_Source%%%d“ „%%d“
Goto Finish

ProcessTree

Set _Directoryname=%1
Set _Directoryname=%_Directoryname:"=%
Set _Prefix=%2
Set _Prefix=%_Prefix:"=%
Echo ProcessTree: %_DirectoryName%
Rem die Dateien beackern if Exist %_DirectoryName%%FileSpec%
For /F „tokens=*“ %%f in (‚dir %_DirectoryName%%FileSpec% /A:-d /B‘) do Call :Rename1File „%_Directoryname%%%f“ „%_Source%%_Prefix%~%%f“
Rem Rekursion in die Unterverzeichnisse
For /F „tokens=*“ %%d in (‚dir %_DirectoryName% /A:d /B‘) do Call :stuck_out_tongue:rocessTree „%_DirectoryName%%%d“ „%_Prefix%~%%d“
Goto :EOF

Rename1File

Set _SourceFileName=%1
Set _SourceFileName=%_SourceFileName:"=%
Set _TargetFileName=%2
Set _TargetFileName=%_TargetFileName:"=%
Rem Wenn Source nicht angegeben, aktuelles Verzeichnis nehmen
If „%_Source%“=="" Set _Source=%CD%Echo Rename1File: %_SourceFileName% – %_TargetFileName%
If „%DRYRUN%“=="" move „%_SourceFileName%“ „%_TargetFileName%“
goto :EOF

Error

Echo. Echo Programmabbruch wegen eines furchtbar schweren Fehlers
Echo.
Set _Error=%1
Set _Error=%_Error:"=%
Echo %_Error%
Echo.
Pause
Goto Finish

DisplayHelp

REM Kommandozeilenhilfe (/?)
Echo.
Echo Aufrufparameter
Echo ---------------
Echo renfiles [„Zielverzeichnis“]
Echo.
Echo Anmerkungen:
Echo ------------
Echo „“ koennen weggelassen werden, wenn kein Leerzeichen im Verzeichnisnamen vorkommt
Echo Default fuer Zielverzeichnis ist das aktuelle Verzeichnis
echo.
Pause
Goto Finish

Finish

Echo Programmende (%ERRORLEVEL%).

Wer damit Probleme hat kann sich gerne per PM bei mir eine „unverwebte“ Vversion anfordern.

Ich rate übrigens vor einem test mit realen Daten -wegen der großen Schäden die ein fehllaufender Automat anrichten kann, dringend dazu, in einer DOS-Box (Kommandozeile) oder gerne auch üner die Windows EInstellungen (Computereigenschaften - Umgebungsvariablen) den Schalter

Set DRYRUN=1

zu setzen, und erst dann die Batch zu starten (ggf. aus der gleichen kommandozeile wie den SET Befehl) dann wird erst mal nichts verändert und man kann an Hand der bildschirmanzeigen in etwa sehen was die Batch tun wird.

Set DRYRUN=

oder einfach eine ander Kommandozeile öffen löscht den Schalter wieder, und beim nächsten Aufruf macht die Batch dann Ernst.

Auch ein Aufruf mit /? ist angeraten, dann wird die Aufrufsyntax ausgegeben.

Sie läuft nun auch per Doppelklick von der GUI aus, die umbenannten Dateien landen dann im gleichen Verzeichnis, in dem sich auch die Batch befindet.

Have Fun

Armin.

Batch lief nicht mit Windows 8.

Debuggte und erfolgreich getestete Version etwas weiter oben im Therad, Message Re^3: Batch-Renamer für Verzeichnisstruktur (30 20.10.2014 18:29)

** Close **