calvin
Goto Top

Mit batch-Skript Zeichenkette "zerlegen"

Hi allerseits,

ich habe mir ein kleines Problem selbst eingebrockt und suche nach einer möglichst effizienten Methode, da wieder rauszukommen face-wink

Hintergrund ist, dass ich jede Menge Dateien umbenennen möchte, deren Dateinamen alle die gleichen Informationen (Spannung, Temperatur, Laufende Nummer, Beschriftung, sonstiger Text) enthalten, die jeweils durch ein _ getrennt sind. Blöderweise habe ich im Laufe der Zeit die Reihenfolge geändert. Das möchte ich jetzt alles einheitlich machen.

Es gibt also Dateien, die z.B. folgende Form haben:

001_100V_20C_E50_*.*
500V_40C_E105_002_*.*
50C_200V_E53_003_*.*

Letztlich sollen alle Dateien in die Form 001_20C_100V_E52_*.* gebracht werden

Mit der Suchfunktion habe ich schon einfache Beispiele zum Umbenennen von Dateien gefunden, so dass das Grundgerüst schon steht. Aber wie lautet die Syntax, wenn ich mit einem batch-Skript einen String (Dateiname) durchsuchen (jeweils bis zum nächsten '_'), und anschließend rausfinden, ob es sich bei dem zuletzt gelesenen um Temperatur, Spannung, usw. handelt?

Kür wäre übrigens noch, wenn das Skript vor dem Umbenennen die Dateien aus einer zip-Datei extrahieren und anschließend wieder zippen würde. Das würde ich aber notfalls noch per Hand machen.

Gruß und Danke für die Aufmerksamkeit
Calvin

Content-Key: 19398

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

Ausgedruckt am: 28.03.2024 um 09:03 Uhr

Mitglied: Biber
Biber 11.11.2005 um 21:26:35 Uhr
Goto Top
Moin Calvin,
dann lass uns aber mit den gleichen Informationen starten..
001_100V_20C_E50_*.*
500V_40C_E105_002_*.*
50C_200V_E53_003_*.*
öhhhm.. was kann denn *.* sein?? Sind da auch "_"-Unterstriche drin? Oder Leerzeichen? Oder Punkte (von einem Datumswert)? Kann von Belang sein..

Letztlich sollen alle Dateien in die Form 001_20C_100V_E52_*.* gebracht werden
Also (nur um zu sehen, ob ich es verstanden habe):
001_ ..Laufende Nummer, immer dreistellig, ggf. mit führenden Nullen aufzufüllen...
nnC_ vermutlich Grad in Celsius.. Gradangaben sind 0 < Grad <=99? max 2stellige Gradangaben?
nnnV_ Volt, Spannung ... Voltangaben sind 0 < Spannung< 999V ....max dreistellig?
Exxx_ Beschriftung ... xx ist zwei- oder dreistellig? Oder soll auch mit führenden Nullen "dreistellig gemacht" werden?
*.* ...zum Beispiel?

Mit der Suchfunktion habe ich schon einfache Beispiele zum Umbenennen von Dateien gefunden,
Find ich vorbildlich...
so dass das Grundgerüst schon steht.
Wo steht das? Ich seh nix...

Aber wie lautet die Syntax, wenn ich mit einem batch-Skript einen String (Dateiname) durchsuchen (jeweils bis zum nächsten '_'),
Im Prinzip mit einer FOR/F ..IN ..DO..-Konstruktion und einem "_" als Trennzeichen. Zeig ich Dir noch.

und anschließend rausfinden, ob es sich bei dem zuletzt gelesenen um Temperatur, Spannung, usw. handelt?
Tja.. Jonglieren mit Variablen.. machen wir dann.

Kür wäre übrigens noch,
..nun mal nicht gierig werden...
wenn das Skript vor dem Umbenennen die Dateien aus einer zip-Datei extrahieren und anschließend wieder zippen würde.
Wenn Du verrätst, was Du als Zipper nimmst und was der für Parameter braucht...
Gibt es denn ein ALT-Directory, wo jetzt die Zips drin sind? Eins zum Arbeiten? Eins für die neuen Zips?
Eins für alle bla_bla_bla_*.* Dateien in entzippter Form?

Das würde ich aber notfalls noch per Hand machen.
Ach was, so schlimm wirds schon nicht werden.

Grüße Biber
Mitglied: Calvin
Calvin 12.11.2005 um 01:00:26 Uhr
Goto Top
Hi biber,

danke für die Antwort. Auf diese Art lerne ich sogar noch was dabei *freu*

>>001_100V_20C_E50_*.*
>>500V_40C_E105_002_*.*
>>50C_200V_E53_003_*.*
öhhhm.. was kann denn *.* sein?? Sind
da auch "_"-Unterstriche drin?
Oder Leerzeichen? Oder Punkte (von einem
Datumswert)? Kann von Belang sein..

Der erste Stern steht für eine beliebige Buchstaben/Ziffernfolge , die manchmal ein "_" enthält. Keine weiteren Sonderzeichen. Diese Zeichenkette ist immer am Ende und soll auch dort bleiben. Diese Zeichenkette ist zwar nicht bei allen Dateien vorhanden, aber wenn man (wie ich hoffe) mit einer Schleife den String von links nach rechts durchsucht, würde ich darin kein Problem sehen.

Der zweite Stern ist die Dateiendung (bmp,fig,txt)

001_ ..Laufende Nummer, immer dreistellig,
ggf. mit führenden Nullen
aufzufüllen...

ja, dreistellig mit führenden Nullen.

nnC_ vermutlich Grad in Celsius..
Gradangaben sind 0 < Grad <=99? max
2stellige Gradangaben?

Ja, zweistellige Gradangaben.

nnnV_ Volt, Spannung ... Voltangaben sind 0
< Spannung< 999V ....max dreistellig?

Voltangaben sind drei oder vierstellig ohne führende Nullen.

Exxx_ Beschriftung ... xx ist zwei- oder
dreistellig? Oder soll auch mit
führenden Nullen "dreistellig
gemacht" werden?

xx ist eine zwei- oder dreistellige Zahl ohne führende Nullen

*.* ...zum Beispiel?

hier ist das "schlimmste" Beispiel: MF1_fig1.bmp

Hier mal mein bisheriges Gerüst mit jeder Menge Pseudocode face-wink

for %%i in (*.*) do call :entpacken "%%i"  
goto ende

:entpacken

:: Entpacke %1
cd Verzeichnis_in_das_entpackt_wurde
for %%j in (*.*) do call :loop "%%j"  
::Dateien wieder zippen
cd Verzeichnis_mit_den_zip_Files
::Zurück zur Schleife in Zeile 1 mit Variable i.

:loop
Set DateinameAlt=%2
Set DateinameNeu=
Set Hilfe=
Set Nummer=
Set T=
Set U=
Set E=
Set Stringende=

::Pseudocode an
:: zaehler=0
:: Per Schleife den Dateinamen zeichenweise von links nach rechts durchlaufen
::::: Bedingung1: letztesZeichen weder "." noch "_" 
::::::::: Hilfe=%Hilfe%letztes gelesenes Zeichen
::::: sonst:
::::::::: zaehler = zaehler + 1
::::::::: Prüfen, ob Hilfe = Temperatur, Spannung, usw.
::::::::: Entsprechender Variable zuordnen
::::::::: Set Hilfe=
::::::::: Bedingung2: wenn zaehler==4 (d.h. entweder ist das letzteZeichen "." oder das vierte "_") 
::::::::::::: Stringende=restliche Zeichen
::::::::: Ende Bedingung2
::::: Ende Bedingung1
:: Schleifenende
::Pseudocode Ende

Set DateinameNeu=%Nummer%_%T%_%U%_%E%%Stringende%

ren %2 %DateinameNeu%
::zurück zur Schleife mit Variable j.

:ende

Im Prinzip mit einer FOR/F ..IN
..DO..-Konstruktion und einem "_"
als Trennzeichen. Zeig ich Dir noch.

/F habe ich auf meiner heutigen Suche mehrfach gefunden. Was bedeutet das?

Wenn Du verrätst, was Du als Zipper
nimmst und was der für Parameter
braucht...

Gute Frage *re* Winzip ist vorhanden. Ebenso die in WindowsXP integrierte zip-Funktion. Wie die Übergabeparameter lauten, weiß ich aber nicht. Wie kann ich das rausfinden?

Gibt es denn ein ALT-Directory, wo jetzt die
Zips drin sind? Eins zum Arbeiten? Eins
für die neuen Zips?
Eins für alle bla_bla_bla_*.* Dateien
in entzippter Form?

Was meinst du damit? Es gibt ein Verzeichnis, in dem die zip-Dateien sind. Sonstige Verzeichnisse anlegen soll nicht das Problem sein face-wink

Ich hoffe, das reicht erstmal. Bin gespannt, wie brauchbar meine Ansätze sind.

Gruß
Calvin
Mitglied: Biber
Biber 12.11.2005 um 02:48:53 Uhr
Goto Top
Danke, Calvin,
für die ausführliche Antwort.
Jetzt ist es nicht mehr ganz so schwammig (kein Vorwurf, aber ein Außenstehender kann nicht alle Rahmenbedingingen kennen, die Dir "selbstverständlich" sind).

Gibt es denn ein ALT-Directory, wo jetzt die Zips drin sind?
Eins zum Arbeiten?
Eins für die neuen Zips?
Eins für alle bla_bla_bla_*.* Dateien in entzippter Form?

Was meinst du damit? Es gibt ein Verzeichnis, in dem die zip-Dateien sind. Sonstige Verzeichnisse anlegen soll nicht das Problem sein

Ich meinte damit: Im Moment liegen sicherlich die Zip-Dateien in einem Ordner (Beispiel: "X:\Messungen").
In diesen Zip-Dateien sind alle Einzeldateien im "alten", im heutigen Namensformat.
Laut Plan & Theorie werden die Einzeldateien entpackt (uuups-Nr-1, und wenn in zwei *.Zips eine gleichnamige Datei ist??) und dann umbenannt.
Uuuups-Nr-2 ... und wenn da Dateinamenskollisionen auftreten? Nicht dass uns da eine Datei verloren geht...
Wenn dann alle Dateien umbenannt worden sind... wie ist dann die Zip-Mimik? Gab es vorher drei Zip-Dateien ZipA.zip, ZipB.zip, ZipC.zip und sollen jeweils die darin enthaltenen Dateien danach un eine ZipA_neu.zip, ZipB_neu.zip und ZipC_neu.zip?? Oder das ganze Geraffel in eine große ZIP-Datei??
Oder lieber doch erstmal alle Einzel-Dateien in einem (Extra-)Ordner liegen lassen und die Zipperei als Extra-Batch-Mimik machen?
An der Stelle kann es sein, dass Du (fachlich und inhaltliche) Anforderungen hast - kann ich aber nicht wissen.
Die Umbenennerei.. okay, da kenn ich halbwegs die Linie.. nach welchen Kriterien Du alles Zippen willst.. na ja, hat auch noch einen Tag Zeit.

Zu Deiner Frage, ob und wie sich z.B. Winzip via CMD-Line aufrufen lässt... *achselzuck*... recherchieren. Zur Not gibt es ja Pkzip/Pkunzip o.ä. vom CMD aufrufbare Freeware-Tools, die ja schließlich das ZIP-Format erst verbreitet haben. Die sind also sicherlich "Zip-kompatibel".
Zur Frage, was "For /F ..IN..DO" macht... siehe "FOR /?" oder in den Tutorials in "Batch & Shell"

Ich schau mir Deinen Krams mal am Wochenende an.

Grüße Biber
Mitglied: Calvin
Calvin 12.11.2005 um 11:33:20 Uhr
Goto Top
Puh, da denkt man, man hätte alles bis ins Kleinste beschrieben und schon kommt ein Außenstehender und findet immer noch Unklarheiten face-wink

Probleme mit doppelten Dateinamen wird es nicht geben.

Der Ablauf sollte folgendermaßen sein:

Ich habe einen Ordner, in dem die zip-Dateien sind, die nach dem oben angesprochenen Schema benannt sind.
In der zip-Datei sind 4 oder 5 Dateien, die alle nach dem selben Aufbau benannt sind, wie die zugehörige zip-Datei. Diese unterschieden sich nur in einem zusätzlichen String am Ende und in der Dateiendung

z.B. 100V_20C_E50_001.zip
-> entzippen ergibt die Dateien
-> 100V_20C_E50_001.txt
-> 100V_20C_E50_001_MF1_fig1.fig
-> 100V_20C_E50_001_MF1.bmp
usw.

Diese Dateien sollen alle umbenannt werden in
001_20C_100V_E50.txt
001_20C_100V_E50_MF1_fig1.fig
001_20C_100V_E50_MF1.bmp
usw.

Anschließend diese Dateien wieder mit dem neuen Namen in die Datei zippen
001_20C_100V_E50.zip

Nächste zip-Datei entzippen, usw.

Die anderen Sachen (for /? und Übergabeparameter für zip-Programm) werde ich im Laufe des Tages mal anschauen.

Gruß
Calvin
Mitglied: Biber
Biber 12.11.2005 um 13:13:55 Uhr
Goto Top
@Calvin
>Puh, da denkt man, man hätte alles bis ins Kleinste beschrieben und schon kommt ein Außenstehender und findet immer noch Unklarheiten face-wink

Na, hör ma... wenn Du das gleich vernünftig beschrieben hättest, hätten wir schon vor Tagen anfangen können .. face-big-smile

Nein, im Ernst - ich finde Deine Problembeschreibung vorbildlich und werde auch ggf. darauf verweisen von anderen Threads aus.
Meine Erfahrung ist nun mal - je länger und genauer die Analyse und Zielanforderung vor dem Eintippen der ersten Code-Zeile, desto kürzer und robuster wird der Code. Und desto schneller passt die Lösung auch.
Hier im Forum gibt es leider manchmal die gegenteiligen Extreme - das Problem wird beschrieben als "wie kann ich eine IP ermitteln?" und nach dreimal Hin- und Herposten stellt sich heraus, dass ein Konkurrenzprodukt zu DynDys entwickelt werden soll oder ähnliches.

Also danke fürs geduldige Erklären.

Grüße
Biber
Mitglied: Biber
Biber 12.11.2005 um 22:03:48 Uhr
Goto Top
So, Calvin,

eine kurze Skizze hätte ich.. einiges wäre kürzer gegangen, aber ich wollte es lesbar halten.
::-------Snipp FileRenamer.bat.
@echo off & setlocal
Set "oldZipDir=Z:"  && rem Da sind die heutigen Zips   
Set "newZipDir=Z:\newZipDir" && rem Da kommen die neuen hin  
Set "workDir=Z:\temp" && rem da benennen wir um  
for %%i in (%workdir% %newZipDir%) do If not exist %%i md %%i
for /f %%i in ('dir /b /A:<dummy>-D %oldzipDir%\*.zip') do call :entpacken "%%~dpnxi" %workdir%  
goto :eof
~~~~~~~~
:entpacken 
:: Entpacke %~1 in WorkDir %2........ den machen wir später
Echo [Simulation] Entpacke %~1 in WorkDir %2
:: Wechsel in das Verzeichnis_in_das_entpackt_wurde 
PushD %2
for %%j in (*.*) do call :process1file %%j 
Echo [Simulation] Dateien wieder zippen ...machen wir später
PopD
:: Wechsel ins das Verzeichnis_vorher (?? das mit_den_zip_Files?)
::Zurück zur aufrufenden FOR-Schleife
goto :eof
~~~~~~~~~
Die Testdatenfälle/Testdateinamen in %workdir:
001_100V_20C_E50_bla.txt
001_100V_20C_E50_blubb.txt
001_100V_20C_E50_blubb_4711.gif
100V_250C_004_E50_0815.gif
100V_250C_004_E50_0815.txt
E605_300V_50C_007_heinz.txt
E605_300V_50C_007_hugo.txt
~~~~~~~
:process1file
:: Parameter %1 ist der "alte" Dateiname... 
For %%i in (lfdnr U T E Rest dummy) do set "%%i="  
For /F "tokens=1-4* delims=_" %%a in ("%~n1") do (  
     (set "rest=%%e%~x1") & For %%x in (%%a %%b %%c %%d) do call :sortIt %%x  
)
Echo INFile=%1 
Echo ....Nebenrechnung: E=%E% U=%U% T=%T% LfdNr=%LfdNr% Rest=%Rest%
echo OUTFile: %LfdNr%_%T%_%U%_%E%_%Rest%  [Ergebnis-Simulation]
echo.
:: UNCOMMENT LATER Set "DateinameNeu=%LfdNr%_%T%_%U%_%E%_%Rest%" 
:: UNCOMMENT LATER Rename %1 %DateinameNeu%
goto :eof
~~~end of process1file


~~~~~~~
:sortIt
Set "Dummy=%1"  
:: echo Dummy %dummy% par1:%1
IF /i [%Dummy:~-1,1%]==[V] (
 set "U=%Dummy%"  
 goto :eof
) 
IF /i [%Dummy:~-1,1%]==[C] (
 set "T=%Dummy%"  
 goto :eof
)
IF /i [%Dummy:~0,1%]==[E] (
 set "E=%Dummy%"  
 goto :eof
)
set "LfdNr=%Dummy%"  
goto :eof

~~~~~~~end of sortIt
::---end of FileRename.bat
Der Output von diesem Schnipsel wäre:
> FileRenamer.bat

[Simulation] Entpacke Z:\test.zip in WorkDir Z:\temp
INFile=001_100V_20C_E50_bla.txt
....Nebenrechnung: E=E50 U=100V T=20C LfdNr=001 Rest=bla.txt
OUTFile: 001_20C_100V_E50_bla.txt  [Ergebnis-Simulation]
INFile=001_100V_20C_E50_blubb.txt
....Nebenrechnung: E=E50 U=100V T=20C LfdNr=001 Rest=blubb.txt
OUTFile: 001_20C_100V_E50_blubb.txt  [Ergebnis-Simulation]
INFile=001_100V_20C_E50_blubb_4711.gif
....Nebenrechnung: E=E50 U=100V T=20C LfdNr=001 Rest=blubb_4711.gif
OUTFile: 001_20C_100V_E50_blubb_4711.gif  [Ergebnis-Simulation]
INFile=100V_250C_004_E50_0815.gif
....Nebenrechnung: E=E50 U=100V T=250C LfdNr=004 Rest=0815.gif
OUTFile: 004_250C_100V_E50_0815.gif  [Ergebnis-Simulation]
INFile=100V_250C_004_E50_0815.txt
....Nebenrechnung: E=E50 U=100V T=250C LfdNr=004 Rest=0815.txt
OUTFile: 004_250C_100V_E50_0815.txt  [Ergebnis-Simulation]
INFile=E605_300V_50C_007_heinz.txt
....Nebenrechnung: E=E605 U=300V T=50C LfdNr=007 Rest=heinz.txt
OUTFile: 007_50C_300V_E605_heinz.txt  [Ergebnis-Simulation]
INFile=E605_300V_50C_007_hugo.txt
....Nebenrechnung: E=E605 U=300V T=50C LfdNr=007 Rest=hugo.txt
OUTFile: 007_50C_300V_E605_hugo.txt  [Ergebnis-Simulation]
INFile=test.zip
....Nebenrechnung: E= U= T= LfdNr=test Rest=.zip
OUTFile: test____.zip  [Ergebnis-Simulation]
[Simulation] Dateien wieder zippen ...machen wir später
Die Zipperei/Entzipperei habe ich weggelassen... da warte ich, bis Du einen Zipper hast, der sich via CMD-Line aufrufen lässt und der lange Dateinamen kann.
Die älteren, die ich noch bei mir auf dem Rechner habe, können zum Teil nur die "8.3-Namenskonvention".
Aber z.B. ARJ.exe (letzte bekannte Adresse in meiner alten Version: robjung@world.std.com) erlaubt sogar das Umbenennen von Datei im Archiv... wenn Du so ein Teil auftreibst, ist sogar das temporäre Entpacken/Packen unnötig.

So, ich mach mir erstmal ein Becks auf.
Schönen Abend
Biber
Mitglied: Calvin
Calvin 13.11.2005 um 15:15:32 Uhr
Goto Top
Hi biber *ehrfürchtigniederknie*

vielen Dank für deine Mühe. Sieht schon so gut wie perfekt aus. Und das das (ent)zippen ist vermutlich auch nicht mehr so schwer. Mit einem möglichen zip-Programm werde ich mir aber erst in den nächsten Tagen beschäftigen können.
Habe gerade mit dem Skript ein bißchen rumgespielt, um alles besser verstehen zu können. Das hat schon fast alle meiner Fragen beantwortet face-smile

Aber eins habe ich dann doch noch.
for /f %%i in ('dir /b /A:<dummy>-D %oldzipDir%\*.zip') do call :entpacken "%%~dpnxi" %workdir%
Was bedeutet das in der Klammer?

Eine kleine Änderung/Ergänzung habe ich noch gemacht. So sieht der entsprechende Teil jetzt aus:

::~~~~~~~ 
:process1file 
:: Parameter %1 ist der "alte" Dateiname...  
For %%i in (lfdnr U T E Rest dummy) do set "%%i="   
For /F "tokens=1-4* delims=_" %%a in ("%~n1") do (   
(set "rest=%%e%~x1") & For %%x in (%%a %%b %%c %%d) do call :sortIt %%x   
) 
Echo INFile=%1 
Echo ....Nebenrechnung: E=%E% U=%U% T=%T% LfdNr=%LfdNr% Rest=%Rest%
IF /i [%Rest:~0,1%]==[.] ( 
echo OUTFile: %LfdNr%_%T%_%U%_%E%%Rest% [Ergebnis-Simulation] 
Set "DateinameNeu=%LfdNr%_%T%_%U%_%E%%Rest%"  
) ELSE (
echo OUTFile: %LfdNr%_%T%_%U%_%E%_%Rest% [Ergebnis-Simulation] 
Set "DateinameNeu=%LfdNr%_%T%_%U%_%E%_%Rest%"  
)
echo. 
:: UNCOMMENT LATER Rename %1 %DateinameNeu% 
goto :eof 
::~~~end of process1file 

Gruß
Calvin, der gestern ein Hefeweizen auf dich getrunken hat face-smile
Mitglied: Biber
Biber 13.11.2005 um 15:53:09 Uhr
Goto Top
Moin, Calvin,

sorry, ich war wohl etwas sparsam mit den Kommentaren.

for /f %%i in ('dir /b /A:<dummy>-D %oldzipDir%\*.zip') do call :entpacken "%%~dpnxi" %workdir%

Was bedeutet das in der Klammer?
('dir /b /A:<dummy>-D %oldzipDir%\*.zip')
wenn etwas in einfachen Anführungszeichen steht, ist es ein Programmaufruf, der den Output, also den Part für die DO-Anweisung liefern soll. Hier wird also DIR aufgerufen.
DIR /b ... /b liefert nur die nackten Dateinamen, ohne Uhrzeit, Größe etc.
/A:D würde nur alle Dateien mit "A"=Attribut "D"=Directory liefern. Ich will das Gegenteil - Nur alle mit Attribut "kein Directory", also "/A:<dummy>-D".
Ist bei Dir nicht nötig... in meinem Test-Directory gestern hatte ich Unterverzeichnisse *gg
%oldzipDir%\*.zip ich will den DIR-Befehl ja nur anwenden auf alle ZIP-Dateien in %oldzipDir%

Anmerkung zu :process1file
Das Setzen des neuen Names mit "Set DateinameNeu=.." hatte ich noch aus Deiner Vorlage übernommen. Nötig ist dieser Zwischenschritt nicht. Kann auch direkt in die Rename-Zeile eingearbeitet werden. Also da, wo jetzt "Set DateinameNeu=" steht, statt dessen das "Rename %1" hinschreiben.

Habe gestern parallel zu Deinem Hefeweizen ein Becks getrunken...
.. aber ich lasse mich GERN zu Hefeweizen überreden. face-wink Ich liebe Berührungen mit fremden Kulturwelten..

Schönen Sonntag noch
Biber