sodele
Goto Top

Dateien überprüfen und umbenennen

Aufgabe: Nachdem durch eine Batch aus verschiedenen Dateien im Ordner neue Dateien generiert wurden, soll zum Abschluss erst eine Überprüfung stattfinden, ob die neuen Dateien tatsächlich vorhanden sind (wenn nicht Fehlermeldung ausgeben) bevor die Orignaldateien verschoben werden. Außerdem soll in den neuen Dateien der Schluss des Dateinamens mit fixer Länge entfern werden.

Hallo zusammen!

Ich habe mal wieder ein Problem, bei dem ich auf eure Hilfe hoffe. In einem Ordner befinden sich verschiedene Dateien, deren Namen wie folgt aufgebaut sind:

Dateiname1 [20110506].txt
[rev] Dateiname2 [20110615].txt
Dateiname3 [20110905].txt
...

Aus diesen Dateien werden per Batchdatei ein paar der Inhalte in csv-Dateien zusammengefasst, die dann so benannt rauskommen:

Dateiname1 [20110506].csv
[rev] Dateiname2 [20110615].csv
Dateiname3 [20110905].csv
...

Wichtig ist, dass da mehr als nur eine eckige Klammer stehen kann, die einzelnen Teile jedoch immer durch ein Leerzeichen voneinander getrennt stehen. Jetzt möchte ich zum Abschluss dieser Batchdatei noch einfügen, dass er vor der Verschiebung der Original-Textdateien in einen anderen Ordner schaut, ob die neuen Dateien auch wirklich generiert wurden und außerdem hätte ich noch gern, dass in den Namen der csv dann das Datum in eckigen Klammern einschließlich dem vorangehenden Leerzeichen gelöscht wird.

Mein bisheriger Ansatz

@echo off & setlocal


for %%i in ("*.txt") IF EXIST "%%~ni.csv" DO move %%i originale\  ELSE goto :errormessage  

REM Loesche letzten Teil des Dateinamens
FOR %%a in (* [*.csv) do (
  FOR /f "delims= [ tokens=1,2" %%i in ("%%a") do rename "%a%b.csv" "%a.csv"  
)

:errormessage
echo Die Dateien konnten nicht gefunden werden
set /p frage="Drücke eine beliebige Taste um abzubrechen."  
if "%frage%" == "" goto end  

:end
EXIT

funktioniert natürlich nicht...

1. Aus irgendeinem Grund verschiebt er die Originale nicht, auch wenn die dazugehörigen csv-Dateien vorhanden sind.
2. Der Ansatz über "blank[" zur richtigen eckigen Klammer, die gelöscht werden soll, zu kommen scheint mir nun doch nicht mehr richtig (auch habe ich das mit dem tokens noch immer nicht wirklich begriffen).
Ist es nicht irgendwie möglich, einfach die letzten 11 Zeichen (also Datum+Klammern+Leerzeichen vor der Klammer) eines Dateinamens zu löschen, ohne dass der gesamte Anfang des Dateinamens überprüft wird? (Externe Umbenennungsprogramme sind im übrigen keine Alternative, da es ja zum Abschluss einer Batch eingefügt werden soll und eben keine einmalige Sache ist).

Könnte mir bitte einer von euch Experten auf die Sprünge helfen?

Content-ID: 174582

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

Ausgedruckt am: 19.12.2024 um 15:12 Uhr

60730
60730 12.10.2011 um 22:05:47 Uhr
Goto Top
Servus,

1) mit dem @echo off wirst du das niemals rausfinden.. WTF?
IF EXIST "%%~ni.csv" DO move %%i originale\ ELSE goto :errormessage
ist falsch
  • if else funktioniert so ohne klammern nicht
if /?
2) schau dir die Anleitung zur For Schleife an
  • Schau dir auch mal Set /? an %PATH:~-10%

Gruß
bastla
bastla 12.10.2011 um 22:07:56 Uhr
Goto Top
if else funktioniert so ohne klammern nicht
... und das DO gehört zum FOR und daher davor ...

Außerdem ist das Springen aus einer Schleife auch keine gute Idee (und das "Nicht-Zurückkehren-wenn-kein-Abbruch-gewünscht-wird" noch weniger) - vielleicht ließe sich ja (auf Basis eines Logs) im Nachhinein etwas entspannter auf die gefundenen Fehler (= nicht gefundenen Dateien face-wink) reagieren ...

Grüße
bastla
Friemler
Friemler 12.10.2011 um 22:09:58 Uhr
Goto Top
Hallo Sodele,

ich habe nur mal kurz drüber geschaut. Grundsätzlich gilt: Alle Variablen/Ausdrücke, die Pfade/Dateinamen enthalten, immer in Anführungszeichen setzen (z.B. %%i in Zeile 4, * [*.csv in Zeile 7) und statt "delims= [ tokens=1,2" das so "tokens=1,2 delims=[ " schreiben.

Zu Deiner Idee, die letzten 11 Zeichen zu extrahieren: Schau dir mal set /? an. Mit set "Var2=%Var1:~-11%" kann genau das erreicht werden.

Gruß
Friemler
bastla
bastla 12.10.2011 um 22:13:55 Uhr
Goto Top
@Friemler
Zu Deiner Idee, die letzten 11 Zeichen zu extrahieren: Schau dir mal set /? an. Mit set "Var2=%Var1:~-11%" kann genau das erreicht werden.
... obwohl: Noch besser ginge das mit
set "Var2=%Var1:~,-11%"
(die sollen ja weg face-wink) ...

Grüße
bastla
Friemler
Friemler 12.10.2011 um 22:20:25 Uhr
Goto Top
@bastla

Jepp, zu schnell geschaut face-wink .

N8
Friemler
Skyemugen
Skyemugen 12.10.2011 um 22:29:59 Uhr
Goto Top
Aloha,

FOR %%a in (* [*.csv) do ( 
  FOR /f "delims= [ tokens=1,2" %%i in ("%%a") do rename "%a%b.csv" "%a.csv"   
... was glaubst du, bewirken %a & %b ? face-wink

greetz André

P.S.:
if "%frage%" == "" goto :eof  
... hm also entweder machst du jetzt
if "%frage%"=="" goto :eof   
daraus oder
if "%frage%" equ "" goto :eof  
weil so mit überflüssigen Leerzeichen sollte man sich beim Bätscheln gar nicht erst angewöhnen.

btw:
set /p frage="Drücke eine beliebige Taste um abzubrechen."
und dann rattert es dennoch zu EXIT? ... dann doch lieber STRG+C zum Abbrechen ... außerdem würde kaum jemand nichts drücken, ist doch eine Falle face-smile
bastla
bastla 12.10.2011 um 22:39:42 Uhr
Goto Top
@skye
... was glaubst du, bewirken %a & %b ? face-wink
Da würde noch nicht mal %%a helfen ... face-wink

Grüße
bastla
Biber
Biber 12.10.2011 um 22:56:56 Uhr
Goto Top
[OT]
Moin Skye,

Zitat von @Skyemugen:

P.S.:
... weil so mit überflüssigen Leerzeichen sollte man sich beim Bätscheln gar nicht erst angewöhnen.
Ja, stimmt schon.
Man sollte auch weniger rauchen und öfters beichten gehen. Und den Müll trennen und nicht so laut Musik hören.
Allerdings gilt das mit den zu vermeidenden trailing and leading blanks beim SETzen von Variablen.
Da werden sowohl Leerzeichen vor wie nach dem Gleichheitszeichen mitgeSETzt.
Set test = whatever
-->Setzt eine Variable namens %TestLEERZEICHEN% auf den Wert LEERZEICHENwhatever

Beim IF-Vergleich allerdings werden Leerzeichen weggeparst.
>set frage=xx

(=22:51:42  D:\temp=)
>if "%frage%" == "" @echo touchdown  

(=22:52:05  D:\temp=)
>if "%frage%" == "xx" @echo touchdown  
touchdown

(=22:52:15  D:\temp=)
>if "%frage%"                              == "xx" @echo touchdown  
touchdown

(=22:52:30  D:\temp=)
>if %frage%                              == xx @echo touchdown
touchdown

(=22:52:54  D:\temp=)
>if %frage%                              ==xx @echo touchdown
touchdown

(=22:53:07  D:\temp=)
>if %frage%                       d       ==xx @echo touchdown
"d" ist syntaktisch an dieser Stelle nicht verarbeitbar.  

(=22:53:24  D:\temp=)
>if %frage%                              ==                        xx @echo touchdown
touchdown

Es würde jedenfalls nicht zu Fehlern im oben zitierten Code führen.

Grüße
Biber
[/OT]
Sodele
Sodele 12.10.2011 um 23:30:35 Uhr
Goto Top
Zitat von @Skyemugen:

btw:
> set /p frage="Drücke eine beliebige Taste um abzubrechen."
und dann rattert es dennoch zu EXIT? ... dann doch lieber STRG+C zum Abbrechen ... außerdem würde kaum jemand
nichts drücken, ist doch eine Falle face-smile

Nun, ich gebe zu, dass es sinnlos erscheinen mag, aber eigentlich war das nur als Notbehelf gedacht, die Batch einfach anzuhalten, bis man eine Eingabe macht, damit man gleich sieht, dass die csv-Dateien gar nicht geschrieben wurden (eben durch einfaches Lesen des Textes). Ohne dem geht die Batch doch einfach zur nächsten Zeile weiter und spult den Rest ab. Ich sollte vielleicht noch dazu sagen, dass es sich in Wahrheit um >50 Dateien handelt, bei unter 10 würde man das Fehlen der csv vermutlich mit nur einem Blick feststellen, aber selbst dann würde die Batch ja zur nächsten Zeile weiterspringen und in dem Fall schnell von Hand STRG+C einzugeben würde dem Sinn entgegenlaufen, dass ich in der Zeit während die Batch läuft was anderes machen kann, als auf den Bildschirm zu schauen, ob alles glatt läuft. Anders ausgedrückt soll das Ganze so ablaufen:

Wenn csv zu txt existiert, dann verschiebe txt in Ordner original\ und arbeite Rest der Batch ab,
Wenn csv zu txt nicht existiert, dann gib eine Fehlermeldung aus und warte auf Abbruch durch Nutzer (damit er Zeit hat die Fehlermeldung zu sehen/lesen). Arbeite den Rest der Batch in diesem Fall NICHT weiter ab.

Im übrigen Danke an Friemler/bastla für den Tipp mit set "Var2=%Var1:~,-11%" Das sieht auf jeden Fall besser aus, als die Tokens/Delims-Lösung. Nur leider hat mich die Hilfefunktion hier nicht wirklich weitergebracht. set setzt doch nur Umgebungsvariablen, aber kann doch nicht die richtigen Dateinamen umschreiben, oder doch?
bastla
bastla 12.10.2011 um 23:36:19 Uhr
Goto Top
Hallo Sodele!
Wenn csv zu txt nicht existiert, dann gib eine Fehlermeldung aus und warte auf Abbruch durch Nutzer (damit er Zeit hat die Fehlermeldung zu sehen/lesen)
Dafür gäbe es doch "pause" - aber wie oben schon erwähnt: Wäre es nicht sinnvoller, alle Dateien zu überprüfen und die Fehlenden in ein Log zu schreiben, anstatt schon bei der ersten nicht vorhandenen Datei den Batch abzubrechen?
set setzt doch nur Umgebungsvariablen, aber kann doch nicht die richtigen Dateinamen umschreiben, oder doch?
Du kannst aber den neuen Dateinamen in einer Variablen erstellen und diese Variable beim "ren" verwenden.

Zu beachten wäre dabei, dass Du entweder "delayedExpansion" (dann sollte es in Deinen Dateinamen kein "!" geben) oder ein Unterprogramm verwenden musst, um die "Umgebungsvariablen" in der Schleife nutzen zu können ...

Grüße
bastla
Sodele
Sodele 12.10.2011 um 23:44:45 Uhr
Goto Top
Ah okay, danke. delayedExpansion ist kein Problem, außer Leerzeichen und eckigen Klammern gibt's zum Glück nichts in den Dateinamen.

Pause hatte ich probiert, aber die hat er mir einfach ignoriert. Könnte natürlich auch daran liegen, dass ich die richtige if-Schleife noch nicht gefunden habe und er eben vermutlich schon vor dem Ende des Befehls abgebrochen hat.

edit: Ein Logfile wäre sicher eine gute Lösung, aber prinzipiell ist zu 98% davon auszugehen, dass wenn er die erste csv schon nicht geschrieben hat, vermutlich auch die anderen nicht geschrieben hat. Es ist also völlig in Ordnung schon beim ersten Fehlen einer csv-Datei abzubrechen, da danach ja eigentlich nur noch ein paar "Aufräumbefehle" wie eben ein letzten Umbenennen und viel wichtiger, das Löschen des Temp-Ordners, in dem noch ein paar andere Hilfsdateien herumliegen, erfolgen sollen (und das soll wirklich NUR geschehen, wenn auch wirklich alle csv da sind). Es ist mir also lieber, er bricht vorher ab, als einfach weiterzuspulen.
Skyemugen
Skyemugen 13.10.2011 um 08:33:26 Uhr
Goto Top
[OT]
Aloha Biber,

I know, ich sagte auch nicht, dass das hier zu einem Fehler führen würde, sondern, dass man sich das gar nicht erst angewöhnen soll, denn sonst überträgt man das irgendwann nämlich wirklich auf das setzen von Variablen face-wink

@bastla, auch hier: I know aber ein Fehler bleibt ein Fehler und wir wollen hier ja keine halbe Arbeit machen face-wink

Anders ausgedrückt: Ich habe mich nicht weiter um die Fehlerbehebung des Themas bemüht, da ich Wiederkauen nicht mag, sondern habe lediglich noch nicht genannte, im Code enthaltene Fauxpas angekreidet.

greetz André
[/OT]
Skyemugen
Skyemugen 13.10.2011 um 08:55:02 Uhr
Goto Top
Aloha,

weil du schreibst

Aus diesen Dateien werden per Batchdatei ein paar der Inhalte in csv-Dateien zusammengefasst, die dann so benannt rauskommen:

frage ich mich: Warum das nicht alles in einem Abwasch geschieht und du das hier extra durchkaust?
Oder anders ausgedrückt, wenn davor schon etwas bätschelt, mach das Paket dann doch größer und steck' nicht zwei Kartons in dieselbe Schublade face-wink

greetz André
pieh-ejdsch
pieh-ejdsch 13.10.2011 um 09:31:57 Uhr
Goto Top
moin André,

... dass man sich das gar nicht erst angewöhnen soll, denn sonst ...
sieht man vllt etwas anderes...
>for %i in (.) do if   1  ==  1   echo gleich

>if 1 == 1 echo gleich
gleich

>for %i in (.) do if "1"=="1" echo gleich

>if "1" == "1" echo gleich
gleich

ich schreibe es immer so, wie es der Interpreter hinschreiben würde: Ist für mich auch Lesbarer - schon beim Testen.
Andere Programmiersprachen haben ja auch "Luft" dazwischen.
>for %i in (.) do if "1" == "1" echo gleich

>if "1" == "1" echo gleich
gleich

Gruß Phil
Skyemugen
Skyemugen 13.10.2011 um 10:00:43 Uhr
Goto Top
Aloha Phil

ich schreibe es immer so, wie es der Interpreter hinschreiben würde
verstehe, Sauerei! face-smile
Ich war da konservativ, siehe Hilfe-Beispiele face-wink

Zeichenfolge1==Zeichenfolge2
IF %ERRORLEVEL% LEQ 1 goto ok

da ich jedoch inzwischen dieses Doppelistgleich nicht mehr sehen kann, tendiere ich i.d.R. so oder so zu if "X" equ "X" aber genug jetzt mit dem Offtopic zum if IF contains space face-wink

greetz André
bastla
bastla 13.10.2011 um 10:30:07 Uhr
Goto Top
[OT]@Skye
Ich hatte ja nicht Deine Kritik kritisiert, sondern nur anmerken wollen, dass in Gestalt des fehlenden zweiten Prozentzeichens noch ein weiterer Fehler auf seinen Auftritt wartete ... face-wink

Grüße
bastla
[/OT]
Sodele
Sodele 13.10.2011 um 14:47:37 Uhr
Goto Top
Weil ein Drittprogramm mit der CSV gefüttert wird, die keine txt akzeptiert (und von der ja auch nicht alle Daten gebraucht werden) und meine Batch-Fähigkeiten für so komplexe Sachen zu beschränkt sind (nachdem ich ja nicht mal das renamen alleine hingekriegt habe) ;)

Okay, nach langem Herumprobieren bin ich nach wie vor nicht auf eine funktionierende Lösung mit der If-Schleife gekommen. Ich werde jetzt einfach direkt eine Abfrage einbauen, ob man den Rest der Batch weiterlaufen lassen will oder nicht, dann muss man halt erst manuell nachschauen, ob alles da ist.

Was die Umbenennung betrifft, funktioniert das zwar jetzt, der code sieht aber irgendwie mit der Extension unschön aus:

@setlocal enabledelayedexpansion


for %%a in ("*.csv") do (  
set Var1=%%~na
set Var2=!Var1:~,-11%!
ren "%%a" "!Var2!.csv"  
)

Gibt's vielleicht eine professionellere Lösung?
bastla
bastla 13.10.2011 um 19:35:24 Uhr
Goto Top
Hallo Sodele!
Gibt's vielleicht eine professionellere Lösung?
Na klar:
@setlocal enabledelayedexpansion

for %%a in ("*.csv") do (  
    set "Name=%%~na"  
    ren "%%a" "!Name:~,-11%!%%~xa"  
)
Grüße
bastla
Sodele
Sodele 13.10.2011 um 19:46:25 Uhr
Goto Top
Vielen Dank, das sieht wirklich besser aus.