sonnenblume87
Goto Top

Batch-Datei zur Erzeugung von Textdateien (basierend auf einer Ausgangsdatei) je nach Inhalt des Verzeichnisses, for-Schleifen-Problem

Hallo zusammen,

da ich hier schon ein paar hilfreiche Tipps gefunden habe, die mich der Lösung meines Problems näher gebracht haben, hoffe ich, dass mir jemand von euch auch noch bei dem Rest helfen kann. face-smile

Ich schreibe an einer Batch-Datei, mit deren Hilfe Verbindungsdateien für lokale Datenbanken (Firebird) je nach Inhalt des Datenbankordners erstellt werden sollen.
Als Vorlage hierfür dient eine vorhandene Verbindungsdatei im txt-Format.

Die Batchdatei sieht folgenden Ablauf vor:
Zunächst wird eine txt-Datei (datenbanken.txt) erstellt, welche die Dateinamen aus dem Datenbank-Ordner auflistet. Danach wird die Ausgangs-Verbindungsdatei kopiert und in eine txt umgewandelt und umbenannt (neuedsn.txt). Nun soll für jede Zeile in datenbanken.txt ein bestimmter Eintrag in neuedsn.txt gesucht und durch die Zeile aus der datenbanken.txt ersetzt werden. Das ganze wird dann in eine neue Datei gespeichert, wieder in eine Verbindungsdatei umgewandelt und zurückkopiert (in den Ordner mit den Verbindungsdateien).

Soweit so gut, allerdings wirft mir meine Batch-Datei in der Konsole einen Syntaxfehler aus. Ich bin mir relativ sicher, dass es an der ersten for-Schleife (für die Abarbeitung der einzelnen Zeilen in der datenbanken.txt) liegt. Den Suchen-und-Ersetzen Teil habe ich so aus dem Netz kopiert und der funktionierte einzeln (aber ohne die Variable %%f in ausgabe und ersetzungszeichen) wunderbar.

Hier mein Quelltext:

@echo off

rem Löschen der alten DB-Liste
del d:\sw\datenbanken.txt

rem Erstellen der neuen DB-Liste
for /f "delims=" %%i in ('dir d:\sw\db\*.gdb /b') do @echo %%~ni >> d:\sw\datenbanken.txt  

rem Kopieren der Lokal-dsn nach d:\sw
xcopy /q /y "C:\Programme\Gemeinsame Dateien\ODBC\Data Sources\lokal_D.dsn" d:\sw\  

rem Umbenennen der dsn in txt
ren d:\sw\lokal_D.dsn neuedsn.txt

rem Erstellen der neuen dsn-Files
for /f "delims=" %%f in (d:\sw\datenbanken.txt) do (  
	
	REM Ersetzen des DBNamen in der dsn
	SETLOCAL enabledelayedexpansion

	SET "datei=d:\sw\neuedsn.txt"  
	SET "ausgabe=d:\sw\%%f.txt"  
	SET "suchzeichen=sw.gdb"  
	SET "ersetzungszeichen=%%f.gdb"  
	
	REM Datei zeilenweise auslesen 
	REM und in Variable "zeile" schreiben  
	FOR /f "delims=" %%j IN ('FINDSTR . "%datei%"') DO (  
	SET zeile=%%j& CALL :ersetzen !zeile!
	)
	GOTO :eof

	:ersetzen
	REM Das Suchzeichen mit dem Ersetzungsteichen tauschen
	SET zeile=!zeile:%suchzeichen%=%ersetzungszeichen%!

	REM Ergebnis in die Ausgabedatei schreiben
	ECHO !zeile!>>%ausgabe%
	GOTO :eof

	:eof
	
	rem Umbenennen der txt in dsn
	ren d:\sw\%%f.txt %%f.dsn

	rem kopieren der neuen dsn
	xcopy /q /y d:\sw\%%f.dsn "C:\Programme\Gemeinsame Dateien\ODBC\Data Sources\"   

	rem löschen des dsn-files unter d:
	del d:\sw\%%f.dsn

	)

rem löschen der neuedsn.txt
del d:\sw\neuedsn.txt

In einem weiteren Schritt sollte noch der Inhalt der vorherige datenbanken.txt (also vor dem löschen) mit C:\Programme\Gemeinsame Dateien\ODBC\Data Sources\ abgeglichen werden und Dateien, die mit den EIntragungen in der txt übereinstimmen gelöscht werden.
Ich würde mich sehr freuen, wenn ihr hierbei auch helfen könntet. face-smile

Liebe Grüße,
Christiane

Content-Key: 117398

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

Printed on: April 19, 2024 at 19:04 o'clock

Mitglied: 77559
77559 Jun 03, 2009 at 17:12:04 (UTC)
Goto Top
Hallo Chistiane,

willkommen im Forum.

Du hast scheinbar einige Codeschnipsel die als SUB realisiert waren einfach in deine Schleife kopiert, das geht so nicht.
Die goto :Eof innerhalb der Schleife lassen die ganze Batchdatei abbrechen und die Label innerhalb der Schleifen funktionieren auch nicht.

Ich muss gerade den Platz wechseln, melde mich nochmal wenn kein anderer schneller ist face-wink

Gruß
LotPings
Mitglied: 77559
77559 Jun 03, 2009 at 18:02:28 (UTC)
Goto Top
Hallo nochmal,

nach einiger Trockenübungs-Gehirnakrobatik bin ich zu dem Schluß gekommen
das die ganze hin und her Kopiererei eigentlich entfallen könnte.

Diese 2 gestaffelten For Schleifen sollten eigentlich den Zweck erfüllen.
Ob die Datenbank.txt überhaupt nötig ist weiß ich nicht, sie wird in einem Rutsch mit
neu erstellt.

@echo off
SetLocal EnableDelayedExpansion
rem globale Variablen
SET "Vorlage=C:\Programme\Gemeinsame Dateien\ODBC\Data Sources\lokal_D.dsn"  
SET "ZielPfad=C:\Programme\Gemeinsame Dateien\ODBC\Data Sources\"  
SET "suchzeichen=sw.gdb"  

rem Löschen der alten DB-Liste
del d:\sw\datenbanken.txt

rem Erstellen der neuen DB-Liste
FOR /f "delims=" %%i in ('dir d:\sw\db\*.gdb /B /ON /A-D') do (  
  >>"d:\sw\datenbanken.txt" echo/%%~ni  
  Type NUL>"%ZielPfad%%%~ni.dsn"  
  FOR /f "delims=" %%j IN ('Type "%Vorlage%" ') DO (  
    Set "Zeile=%%~j"  
    >>"%ZielPfad%%%~ni.dsn" Echo/!Zeile:%suchzeichen%=%%~nxi!  
  )
)

Gruß
LotPings

Edit zuviel gekürzt der Setlocal fehlte
Edit2: Ein %-Zeichen fehlte in Zeile 17
Edit3: Alte dsn muss gelöscht werden
Member: Sonnenblume87
Sonnenblume87 Jun 04, 2009 at 07:05:32 (UTC)
Goto Top
Hi LotPings,

erstmal Danke für die Antwort. Ich habe deine Batch-Datei ausprobiert und sie erzeugt zwar die .dsn-Files allerdings nicht richtig.

Die Vorlage dsn sieht so aus:
[ODBC]
DRIVER=Firebird/InterBase(r) driver
UID=USER
DIALECT=1
CHARSET=ISO8859_1
Dbname=d:\sw\db\sw.gdb


Die Zieldatei sollte also nach dem Suchen und Ersetzen z.B. so aussehen:
[ODBC]
DRIVER=Firebird/InterBase(r) driver
UID=USER
DIALECT=1
CHARSET=ISO8859_1
Dbname=d:\sw\db\anderedb.gdb


Deine Batch macht aber das:
Zeile:sw.gdb=anderedb.gdb
Zeile:sw.gdb=anderedb.gdb
Zeile:sw.gdb=anderedb.gdb
Zeile:sw.gdb=anderedb.gdb
Zeile:sw.gdb=anderedb.gdb
Zeile:sw.gdb=anderedb.gdb

???

Kannst du mir da nochmal weiterhelfen?
Wäre super wenn du mir dann den Quellcode innerhalb der Schleifen auch nochmal genauer erklären könntest. face-smile

Danke und Gruß,
Christiane
Mitglied: 77559
77559 Jun 04, 2009 at 09:33:17 (UTC)
Goto Top
Zitat von @Sonnenblume87:
Kannst du mir da nochmal weiterhelfen?
Die Ersetzung funktionierte nicht mit DelayedExpansion, habe hier ein Ersatzkonstrukt, damit gehts.
@echo off
rem globale Variablen
SET "SucheZ=sw.gdb"  
SET "Vorlage=C:\Programme\Gemeinsame Dateien\ODBC\Data Sources\lokal_D.dsn"  
SET "ZielPfad=C:\Programme\Gemeinsame Dateien\ODBC\Data Sources\"  
Set DBMaske=D:\sw\db\*.gdb
Set DBListe=D:\sw\datenbanken.txt
FOR /f "delims=" %%A IN ('Type "%DBListe%" ') Do Del /Q "%ZielPfad%%%A.dsn" >NUL 2>&1  
rem Löschen der alten DB-Liste
del %DBListe%

rem Erstellen der neuen DB-Liste
FOR /f "delims=" %%i in ('dir %DBMaske% /B /ON /A-D') do (  
  >>"%DBListe%" echo/%%~ni  
  Type NUL>"%ZielPfad%%%~ni.dsn"  
  FOR /f "delims=" %%j IN ('Type "%Vorlage%" ') DO (  
    Set "Zeile=%%~j"  
    >>"%ZielPfad%%%~ni.dsn" Call Echo/%%Zeile:%SucheZ%=%%~nxi%%  
  )
)
Wäre super wenn du mir dann den Quellcode innerhalb der Schleifen auch nochmal genauer erklären könntest. face-smile

  • Die Äußere Schleife von Zeile 13 bis 20 listet die Datenbanken in %%i auf,
  • Z14 fügt sie der datenbanken.txt hinzu.
  • Z15 löscht den Inhalt der jeweiligen alten dsn oder erstellt sie neu.
  • Die innere For Schleife von Z16 bis Z19 liest die Vorlage Zeile für Zeile in %%j
  • Da die Ersetzung nicht direkt in einer Schleifenvariable stattfinden kann kopiert Z17 %%j in %Zeile%
  • Z18 hängt die bearbeitet Zeile an die neue .dsn an. Damit keine Leerzeichen am Ende der Zeile mitgeschriebene werden steht der Append vorne. Der Pseudo Call sorgt dafür das im ersten Schritt die Suchen/Ersetzen Werte aufgelöst werden und erst im zweiten Schritt die verdoppelten Prozentzeichen um die Variable Zeile.

Gruß
LotPings

Edit: Zeile 8 eingefügt, löscht alle dsn zu Datenbanken.txt
Member: Sonnenblume87
Sonnenblume87 Jun 04, 2009 at 10:23:48 (UTC)
Goto Top
LotPings, du bist jetzt mein persönlicher Held. face-wink
Das funktioniert super.
Ich habe bisher nur kleinere Batch-Dateien zum Hin-und Herkopieren und Aufrufen von Programmen geschrieben, hätte nicht gedacht, dass das diesmal sowas komplexes ist...
Vielen lieben Dank. face-smile

Meinst du bei dem zweiten Schritt kannst du auch noch helfen? Bzw. lässt sich das überhaupt so realisieren?

"In einem weiteren Schritt sollte noch der Inhalt der vorherige datenbanken.txt (also vor dem löschen) mit C:\Programme\Gemeinsame Dateien\ODBC\Data Sources\ abgeglichen werden und Dateien, die mit den EIntragungen in der txt übereinstimmen gelöscht werden."

Es geht hierbei darum, dass in dem Ordner enige dsn-Files mehr liegen, die die Verbindungsdaten zu verschiedenen Datenbanken auf Servern enthalten und diese nicht gelöscht werden dürfen. Durch das neue Batch kommen ja nun immer wieder neue Verbindungen für lokale Datenbanken dazu bzw. werden ersetzt. Ein manuelles Aufräumen wäre möglich, ist jedoch nicht unbedingt für jeden User einfach, da er nicht zwingend die Namen aller nicht u löschenden Verbindungen auswendig kennt.
Es ist davon auszugehen, dass der User im Idealfall jedesmal, wenn er sich eine lokale Datenbank erstellt/kopiert/o.ä. die .bat ausführt, also sollten bis dahin in der datenbanken.txt noch der alte Inhalt stehen (tut er ja auch) und dementsprechend sollten alles Datenbankverbindungen, die mit den Namen in der .txt übereinstimmen zuerst gelöscht werden.
Existiert keine datenbank.txt mehr, weil der User sie per Hand entfernt hat = shit happens, heißt die handvoll Datenbankverbindungen, die dann nutzlos rumliegen, sind egal. ;)

Grüße,
Christiane
Mitglied: 77559
77559 Jun 04, 2009 at 11:58:07 (UTC)
Goto Top
Zitat von @Sonnenblume87:
LotPings, du bist jetzt mein persönlicher Held. face-wink
Nein nein, für Helden-Kostüme bin ich zu alt face-wink

Meinst du bei dem zweiten Schritt kannst du auch noch helfen? Bzw. lässt sich das überhaupt so realisieren?
Ich habe oben Zeile 8 eingefügt, die sollte das erledigen.

"In einem weiteren Schritt sollte noch der Inhalt der vorherige datenbanken.txt (also vor dem löschen) mit
C:\Programme\Gemeinsame Dateien\ODBC\Data Sources\
abgeglichen werden und Dateien, die mit den EIntragungen in der txt übereinstimmen gelöscht werden."
Es geht hierbei darum, dass in dem Ordner enige dsn-Files mehr liegen, die die Verbindungsdaten zu verschiedenen Datenbanken auf Servern enthalten und diese nicht gelöscht werden dürfen.
Ok aber dann brauchst du doch nur eine Batch die alle dsn mit lokalen Datenbanken durchorgelt und prüft ob diese noch existieren.

Es ist davon auszugehen, dass der User im Idealfall jedesmal, wenn er sich eine lokale Datenbank erstellt/kopiert/o.ä. die .bat ausführt, also sollten bis dahin in der datenbanken.txt noch der alte Inhalt stehen (tut er ja auch) und dementsprechend sollten alles Datenbankverbindungen, die mit den Namen in der .txt übereinstimmen zuerst gelöscht werden.
Existiert keine datenbank.txt mehr, weil der User sie per Hand entfernt hat = shit happens, heißt die handvoll Datenbankverbindungen, die dann nutzlos rumliegen, sind egal. ;)
Muss ja nicht sein, die beschriebene Prüfung ist ja nicht schwer, zu klären ist welche Pfade lokal möglich sind.
Muss mal wiederden Rechner wechseln, poste dann noch mal.

Gruß
LotPings
Mitglied: 77559
77559 Jun 04, 2009 at 14:44:05 (UTC)
Goto Top
Als Ergänzung eine Batch Datei die Anhand der in den dsn Dateien enthaltenen Datenbanknamen deren Vorhandensein überprüft.

Eine Einschränkung gibt es, der Findstr Befehl zickt etwas wenn ein Suchbegriff in der letzten Zeile steht und diese nicht mit einem Return abgeschlossen ist.

:: DelOldDsn.cmd :::::::::::::::::::::::::::::::::::::::::::::::::::::
@echo off
SET "Vorlage=C:\Programme\Gemeinsame Dateien\ODBC\Data Sources\lokal_D.dsn"  
SET "ZielPfad=C:\Programme\Gemeinsame Dateien\ODBC\Data Sources\"  
Set "DBPfad=D:\sw\db\"  

Pushd "%ZielPfad%"  
For /F "tokens=1-2* delims=:=" %%A in (  
'Findstr /I /L "Dbname=%DBPfad%\" "*.dsn"^|Find /I /V "lokal_d.dsn" '  
) do if Not Exist "%%C" Echo Die Datenbank %%C existiert nicht,&Del /P "%%A"  
POPD

Noch etwas: wenn der Suchbegriff im Findstr Befehl mit einem Backslash endet, muss ein zweiter Backslash hinzugefügt werden, sonst wird der eine als Escape für das schließende Anführungszeichen betrachtet - das wirft dann Syntaxfehler auf.

Gruß
LotPings

Edit: Wie gewünscht ein paar Erläuterungen.
  • Kern der Batch ist der Findstr in Z09, er durchsucht alle dsn Dateien nach dbname=d:\sw\db\ und gibt Fundstellen in dieser Form aus:
Dateiname.dsn:dbname=D:\sw\db\Dateiname.gdb
%%A %%B %%C
Dateiname.dsn dbname D:\sw\db\Dateiname.gdb
  • Z10 ist dann eigentlich selbsterklärend. Das & hängt einen weiteren Befehl ohne neue Zeile an.

Gruß
LotPings
Member: Sonnenblume87
Sonnenblume87 Jun 05, 2009 at 07:04:32 (UTC)
Goto Top
Hi,

also die Ergänzung mit dem Löschen funktioniert auch wieder super. Ist genau das, so wie es werden sollte. face-smile
Die zweite Batch-Datei ist ne nette Idee aber leider nicht praktikabel, da in dem Data Sources Ordner auch viele dsn-Files liegen zu denen es keine lokale DB gibt, da es Server-DBs sind. Das würde also zuviel löschen.

Aber wie gesagt, die erste Batch-Dateil reicht mir vollkommen aus. face-smile
Nochmal vielen lieben Dank für die schnelle und nette Hilfe. face-smile
Mitglied: 77559
77559 Jun 05, 2009 at 07:23:26 (UTC)
Goto Top
Zitat von @Sonnenblume87:
also die Ergänzung mit dem Löschen funktioniert auch wieder super. Ist genau das, so wie es werden sollte. face-smile
Schön.

Die zweite Batch-Datei ist ne nette Idee aber leider nicht praktikabel, da in dem Data Sources Ordner auch viele dsn-Files liegen zu denen es keine lokale DB gibt, da es Server-DBs sind. Das würde also zuviel löschen.

Keine Angst, diese Batchdatei nimmt nur dsn die einen Eintrag haben der mit "dbname=D:\sw\db\" beginnt.
Ausserdem wird angezeigt was gelöscht würde und erst nach einer Bestätigung tatsächlich gelöscht.
Insofern kannst du das gefahrlos ausprobieren.

Gruß
LotPings
Member: Sonnenblume87
Sonnenblume87 Jun 05, 2009 at 08:17:50 (UTC)
Goto Top
Zitat von @77559:
Keine Angst, diese Batchdatei nimmt nur dsn die einen Eintrag haben
der mit "dbname=D:\sw\db\" beginnt.
Ausserdem wird angezeigt was gelöscht würde und erst nach
einer Bestätigung tatsächlich gelöscht.
Insofern kannst du das gefahrlos ausprobieren.


Achso. Ok, dann werde ich das auch mal ausprobieren. Danke. face-smile
Member: Sonnenblume87
Sonnenblume87 Jun 05, 2009 at 09:43:49 (UTC)
Goto Top
Hi nochmal,

@77559 habe die 2te. Batch jetzt ausprobiert. Das ist ja noch besser als das löschen basierend auf der datenbanken.txt
Ich werde wohl also Zeile 8 aus der ersten .bat wieder rauswerfen. face-wink

Aber magst du mir die 2te Datei nochmal erläutern?
Die meisten Begriffe und die Nutzung der Sonderzeichen sagen mir bisher gar nichts und ehe ich mir jetzt jede help durchlese bzw. mir die Sachen ergoogle, wäre eine programmbezogene Erklärung dann doch besser. face-smile

Grüße,
Christiane
Mitglied: 77559
77559 Jun 05, 2009 at 12:25:23 (UTC)
Goto Top
Zitat von @Sonnenblume87:
Aber magst du mir die 2te Datei nochmal erläutern?
Die meisten Begriffe und die Nutzung der Sonderzeichen sagen mir bisher gar nichts und ehe ich mir jetzt jede help durchlese bzw. mir die Sachen ergoogle,
Aber genau dadurch lernt man selbst am Besten.

wäre eine programmbezogene Erklärung dann doch besser. face-smile
Siehe oben.

Gruß
LotPings