hedgehogi
Goto Top

Batch script: Problem beim Kopieren und bearbeiten, dynamischen Pfad ermitteln

Hallo Community,

leider habe auch ich ein Problem mit meinem batch script und hoffe ihr könnt mir weiter helfen.
Bitte seid nachsichtig mit mir, denn auch ich bin Anfänger.

Zu meinem Problem:
Ich möchte gerne einige Dateien als Sicherheitskopie in den jeweiligen Backup Ordner kopieren. Im Anschluss daran, sollen dann noch bestimmte Dateien im Backup Ordner bearbeitet werden.
Also z.B. die bookmark.txt soll im Text angepasst werden.
Die Ordner Struktur ist in etwa wie folgt:
U:\Nutzer00001
U:\Nutzer00002
U:\Nutzer99999
In den unteren Verzeichnissen befinden sich Dateien, welche gesammelt und in das jeweilige Nutzer Backup Verzeichnis: U:\Nutzer00001\BackUp kopiert werden sollen

Ein bisschen habe ich schon hinbekommen: Ich durchsuche alle Ordner nach den bestimmten Dateien. Nun sollen diese natürlich in den richtigen Ordner kopiert werden und diese dann noch bearbeitet. Könnt ihr mir dabei helfen? Momentan habe ich leider nur einen Ordner hartcodiert, was nicht Sinn der Sache ist.

:: Sucht die gewünschten Dateien und gibt deren Pfad aus.
FOR /F %%i in ('dir /S /b user.dic, bookmark.txt, names.bic, *.id') do (   
  echo %%i|find "BackUp" >nul  
  if errorlevel 1 (
    copy "%%i" "U:\Nutzer00001\Backup\"  
    echo   %%i nach U:\Nutzer00001\Backup kopiert>>%SCRIPT_LOCATION%log.txt
  ) else (
    echo   %%i : kopiertvorgang abgebrochen>>%SCRIPT_LOCATION%log.txt
  )
)

Für Verbesserungsvorschläge bin ich immer zu haben.
Es ist durch die ganzen Parameterabkürzungen schwierig, immer die Beispiele im Forum zu entziffern. Das muss man erstmal lernen.

Content-Key: 338101

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

Ausgedruckt am: 19.03.2024 um 08:03 Uhr

Mitglied: Pedant
Lösung Pedant 17.05.2017 um 21:51:32 Uhr
Goto Top
Hallo Hedgehogi,

Mit echo %%i|find "BackUp" >nul möchtest Du die Unterordner "BackUp" ausschließen, um nicht Sicherungen zu sichern.
Ist es wirklich ratsam die Backup in einem Unterordner der Quelldateien zu sichern.
Würde es sich nicht aufdrängen die Backups zumindest auf ein anderes Laufwerk zu kopieren?

echo %%i : kopiertvorgang abgebrochen ist inhaltlich nicht korrekt. (Abgesehen vom Schreibfehler)
Im "else"-Fall wird der Kopiervorgang nicht abgebrochen sondern für die aktuelle Datei gar nicht gestartet.
Möchtest Du die "negativ" Ausgabe haben, falls nicht könntest Du die "BackUp"-Ordner vorab ausfiltern.

FOR /F %%i in ('dir /S /b user.dic, bookmark.txt, names.bic, *.id ^| find /v "BackUp"') do (   
    copy "%%i" "U:\Nutzer00001\Backup\"  
    echo   %%i nach U:\Nutzer00001\Backup kopiert>>%SCRIPT_LOCATION%log.txt
)
find /v "Zeichenfolge" zeigt alle Zeilen, die "Zeichenfolge" nicht enthalten.

Zitat von @Hedgehogi:
U:\Nutzer99999
Bist Du Dir sicher dass Du 99.999 Nutzer hast?

Zitat von @Hedgehogi:
Momentan habe ich leider nur einen Ordner hartcodiert, was nicht Sinn der Sache ist.
Ich bezweifel immernoch dass Du tatsächlich eine Schleife über 99.999 Nutzerordner machen möchtest, aber abgesehen davon ginge das so:
@echo off

set SCRIPT_LOCATION=C:\Skript\
set pfad_ohne_nummer=U:\Nutzer
set /a zaehler=0

:wiederholung
REM zaehler um 1 erhöhen
set /a zaehler+=1

REM zaehler mit führenden Nullen auffüllen
if %zaehler% lss 10 (
  set pfad_mit_nummer=%pfad_ohne_nummer%0000%zaehler%
  goto kopieren
)
if %zaehler% lss 100 (
  set pfad_mit_nummer=%pfad_ohne_nummer%000%zaehler%
  goto kopieren
)
if %zaehler% lss 1000 (
  set pfad_mit_nummer=%pfad_ohne_nummer%00%zaehler%
  goto kopieren
)
if %zaehler% lss 10000 (
  set pfad_mit_nummer=%pfad_ohne_nummer%0%zaehler%
  goto kopieren
)
if %zaehler% lss 100000 (
  set pfad_mit_nummer=%pfad_ohne_nummer%%zaehler%
  goto kopieren
)

:kopieren
REM Vorprüfung
if not exist %pfad_mit_nummer%\BackUp\. goto wiederholen

FOR /F %%i in ('dir /S /b user.dic, bookmark.txt, names.bic, *.id') do (   
  echo %%i|find "BackUp" >nul  
  if errorlevel 1 (
    copy "%%i" "%pfad_mit_nummer%\Backup\"  
    echo   %%i nach %pfad_mit_nummer%\Backup kopiert>>%SCRIPT_LOCATION%log.txt
  ) else (
    echo   %%i : Kopiervorgang abgebrochen>>%SCRIPT_LOCATION%log.txt
  )
)

if %zaehler% lss 99999 goto wiederholen

:ende
echo fertig

Nimm statt copy lieber xcopy.
Das funktioniert im Prinzip genauso, setzt aber bei einem Fehler einen auswertbaren Errorlevel.

Die hier geposteten Code-Schnipsel sind weitgehend ungetestet.

Gruß Frank
Mitglied: Hedgehogi
Hedgehogi 18.05.2017 um 09:20:52 Uhr
Goto Top
Hallo Frank,

vielen Dank für deine Lösung. Es kann manchmal so simpel sein...
Das die Backups auf ein anderes Laufwerk müssen, ist natürlich vollkommen richtig.
Die Nutzeranzahl sollte lediglich das Problem verdeutlichen. Es sind keine 99999.
Ein Problem hat sich noch aufgetan und wollte das im Nachgang erfragen:
Ich habe ja bekanntlich Nutzer0001 - Nutzer9999. Wie ich nun festgestellt habe, werden die *.id Dateien der vorhergehenden Nutzer in den neuen ebenfalls eingespielt.

Nutzer0001: Nutzer0001.id
Nutzer0002: Nutzer0001.id, Nutzer0002.id
...
Nutzer9999: Nutzer0001.id, Nutzer0002.id,...,Nutzer9999.id.
Wie kann ich das verhindern?

Viele Grüße
Mitglied: Pedant
Pedant 18.05.2017 um 09:59:42 Uhr
Goto Top
Hallo Hedgehogi,

Zitat von @Hedgehogi:
Ich habe ja bekanntlich Nutzer0001 - Nutzer9999.
Das ist nicht richtig. Bekannt war Du hättest 99999 Nutzer.
Jetzt sagst Du es wären nur 9999. Okay, das ändert am Programmcode wenig.
Ich kann mir aber immernoch nicht vorstellen, dass Du für Daten von fast 10.000 Nutzern verantwortlich bist und Dir jetzt erst Gedanken machst wie die gesichert werden könnten.

Zitat von @Hedgehogi:
Wie ich nun festgestellt habe, werden die *.id Dateien der vorhergehenden Nutzer in den neuen ebenfalls eingespielt.
Jetzt wo Du's sagst.
Dein Dir-Befehl hat keine Angabe darüber wo gesucht werden soll. Er sucht daher im aktuellen Verzeichnis des aktuellen Laufwerks.
Da offenbar alle Dateien gefunden werden, kann das eigenlich nur sein, wenn das Arbeitsverzeichnis U:\ ist und mit dir /s findest Du dann nicht nur alle namentlich unterschiedlichen id-Dateien aller Nutzer, sondern auch alle namentlich gleichen user.dic, bookmark.txt und names.bic aller Nutzer.

Darüber kannst Du schonmal nachdenken.
Ich schick Dir gleiche eine Lösung und eine Alternative mit xcopy.

Gruß Frank
Mitglied: Pedant
Pedant 18.05.2017 um 11:21:09 Uhr
Goto Top
Hallo Hedgehogi,

geändert habe ich:

  • Fehler in der alten Zeile 47 korrigiert. Dort muss es statt "goto wiederholen" "goto wiederholung" heißen.
  • Führende Nullen um eine Stelle verringert
  • Grenzwert für %zaehler% auf 9999 verringert
  • Verzeichniswechsel (hin und zurück) mit pushd und popd hinzugefügt

@echo off

set pfad_ohne_nummer=C:\Temp\Test\Nutzer
set /a zaehler=0

:wiederholung
REM zaehler um 1 erhöhen
set /a zaehler+=1

REM zaehler mit führenden Nullen auffüllen
if %zaehler% lss 10 (
  set pfad_mit_nummer=%pfad_ohne_nummer%000%zaehler%
  goto kopieren
)
if %zaehler% lss 100 (
  set pfad_mit_nummer=%pfad_ohne_nummer%00%zaehler%
  goto kopieren
)
if %zaehler% lss 1000 (
  set pfad_mit_nummer=%pfad_ohne_nummer%0%zaehler%
  goto kopieren
)
if %zaehler% lss 10000 (
  set pfad_mit_nummer=%pfad_ohne_nummer%%zaehler%
  goto kopieren
)

:kopieren
REM pushd merkt sich das momentane Verzeichnis und wechselt dann ins angegebene. Mehr Infos mit pushd /?
pushd "%pfad_mit_nummer%"  
FOR /F %%i in ('dir /s /b *.id') do (   
echo %%i
)
REM popd wechselt zurück ins von pushd gemerkte Verzeichnis. Mehr Infos mit popd /?
popd

if %zaehler% lss 9999 goto wiederholung

:ende
echo fertig


Hier folgt die Alternative mit xcopy
@echo off
set quelle=U:\
set ziel=D:\NutzerBackup
set logdatei=D:\NutzerBackup\log.txt
set errorlogdatei=D:\NutzerBackup\error.txt

REM Optionales Löschen der vorhergehenden Log-Dateien
if exist "%logdatei%" del "%logdatei%"  
if exist "%errorlogdatei%" del "%errorlogdatei%"  

cd /d "%quelle%"  
echo Nutzer-ID werden gesichert...
xcopy /s /i /c /y /f nutzer????.id "%ziel%" 1>> "%logdatei%" 2>> "%errorlogdatei%"  
echo User-Dic werden gesichert...
xcopy /s /i /c /y /f ?ser.dic "%ziel%" 1>> "%logdatei%" 2>> "%errorlogdatei%"  
echo Bookmarks werden gesichert...
xcopy /s /i /c /y /f ?ookmark.txt "%ziel%" 1>> "%logdatei%" 2>> "%errorlogdatei%"  
echo Names-Bic werden gesichert...
xcopy /s /i /c /y /f ?ames.bic "%ziel%" 1>> "%logdatei%" 2>> "%errorlogdatei%"  

:ende
echo fertig

Mehr Infos mit: xcopy /?

Die Variant erfordert, dass das Ziel kein Unterordner der Quelle sein darf.
Die vorhanden BackUp-Unterordner sollten dann entfernt werden, ansonsten würden sie mitkopiert werden.

Bei user.dic, bookmark.txt und names.bic habe ich beim xcopy-Befehl jeweils den ersten Buchstaben durch ein Wildcard (?) ersetzt, damit diese Dateien auf jeden Fall auch in den Unterverzeichnissen gesucht werden.
Da ? ein Platzhalter für ein beliebiges Zeichen ist, würde bei ?ookmark.txt auch eine Datei namens Lookmark.txt oder Nookmark.txt oder ähnlich kopiert werden.
Ich denke aber, dass das kein Problem ist, da vermutlich keine Dateien existieren, die derart namensähnlich sind.

Gruß Frank
Mitglied: 132895
132895 18.05.2017 aktualisiert um 13:27:24 Uhr
Goto Top
Ich würde das so machen:
PS
gci 'U:\' -Directory | %{  
    gci "$($_.Fullname)\*" -Include 'user.dic','bookmark.txt','names.bic','*.id' -Recurse | ?{$_.Directory.Name -ne 'Backup'} | move-item -Destination "$($_.Fullname)\Backup" -Force  
}
Batch
@echo off
for /f "delims=" %%a in ('dir /b /ad "U:\Nutzer*"') do (  
    for /f "delims=" %%b in ('dir /b /s "%%a" ^| findstr /ie "user\.dic bookmark\.txt names\.bic .id"') do (    
        copy "%%b" "%%a\Backup"  
    )
)
Dir sollte aber klar sein wenn das Teil erneut durchläuft das es die vorhandenen Dateien überschreibt. Da sollte man dann je nach Aufbewahrungsanforderungen mit Datumsordnern arbeiten.
Gruß
Mitglied: Pedant
Pedant 18.05.2017 um 11:59:25 Uhr
Goto Top
Hallo password,

die geschachtelte For-Schleife ist hübsch.

Zitat von @132895:
move "%%b" "%%a\Backup"
move? Bist Du Dir sicher?

Zitat von @Hedgehogi:
Im Anschluss daran, sollen dann noch bestimmte Dateien im Backup Ordner bearbeitet werden.
Also z.B. die bookmark.txt soll im Text angepasst werden.
Diese Anforderung hatten wir bisher noch nicht behandelt.
Was meinste Du mit "soll im Text angepasst werden", nur den Dateinamen oder den Dateiinhalt?
Hast Du das schon selbst gelöst?
Falls nicht, dann formulier die Aufgabenstellung bitte konkreter und beschreib wie weit Du damit schon bist.

Gruß Frank
Mitglied: 132895
132895 18.05.2017 aktualisiert um 12:00:42 Uhr
Goto Top
Zitat von @Pedant:
move? Bist Du Dir sicher?
Uups übersehen.
Mitglied: Pedant
Pedant 18.05.2017 um 12:05:40 Uhr
Goto Top
Hallo passwort,

Zitat von @132895:
copy"%%b"
jetzt ist Dir das Leerzeichen verloren gegangen.

Gruß Frank

PS: Noch sechs weitere Klug###er-Kommentare, dann bin ich auch endlich ein Level 2.
Mitglied: Hedgehogi
Hedgehogi 18.05.2017 um 16:47:33 Uhr
Goto Top
Erstmal vielen Dank.
Ich habe euren Vorschlag bei mir einarbeiten können und durch eure Hilfe funktioniert das kopieren wie gewünscht. DANKE!
Manchmal kann die Lösung so einfach sein...

Beim Text anpassen soll folgendes geschehen:
In der user.dic (An sich steht dort auch nur einfacher text drin, wie in einer txt) sollen bestimmte Schlüsselwörter bearbeitet werden:
Die Schlüsselwörter links sind oftmals vorhanden und sollen um den rechten Wert verändert werden:
Ports=TCPIP
Setup=900100
InstallMode=0
InstallType=8

Diese Schlüsselworte, bzw. Zeilen sollen aus der Datei gelöscht werden:
Cache=
Desktop=

Momentan sieht es bei mir wie folgt aus (bin damit nicht zufrieden und funktionieren tut es auch noch nicht... gerade beim if).

For %%a In ("Ports=" "Setup=" "InstallMode=" "InstallType=") Do (
set value=%%a
For /f "tokens=1,2* delims==" %%f In (%pfad%\user.dic) Do (
REM set nval=%%f=%%j
echo %%f _____ %value%
if "%%f"==%value% (
REM set nval=%%f=%value%
REM echo %%f _____ %value%
)
REM echo !nval!>>%pfad%\user.dic
)
)


Es geht 100%ig eleganter, aber mit Batch bin ich noch ein Grünschnabel und muss mit dem erstmal klar kommen.

Viele Grüße
Mitglied: Pedant
Pedant 18.05.2017 um 18:55:04 Uhr
Goto Top
Hallo Hedgehogi,

Zitat von @Hedgehogi:
In der user.dic
Poste doch mal einen repräsentatives Inhaltsbeispiel, falls der (auch nach Zensierung) nicht zur privat ist.


Zitat von @Hedgehogi:
Die Schlüsselwörter links sind oftmals vorhanden und sollen um den rechten Wert verändert werden:
Ports=TCPIP
Setup=900100
InstallMode=0
InstallType=8
Sind das jeweils komplette Zeilen, die man auch komplett ersetzen könnte, also
beginnt eine Zeile mit "Ports=" dann schreib eine Zeile mit "Ports=TCPIP"

Was soll passieren wenn ein Schlüsselwort nicht vorhanden sein sollte? Ignorieren oder zusätzliche Zeile anhängen oder einfügen?


Zitat von @Hedgehogi:
For %%a In ("Ports=" "Setup=" "InstallMode=" "InstallType=") Do (  
  set value=%%a
  For /f "tokens=1,2* delims==" %%f In (%pfad%\user.dic) Do (  
    REM set nval=%%f=%%j
    echo %%f _____ %value%
    if "%%f"==%value% (  
      REM set nval=%%f=%value%
      REM echo %%f _____ %value%
    )
    REM echo !nval!>>%pfad%\user.dic
  )
)
Zum bisherigen Code, nur ein paar erste Bemerkungen:

Generell: Code schreibt man in einem Beitrag in code-Tags (siehe Formatierungen in den Beiträgen ).

In Zeile 1 fehlen noch Cache= und Desktop=

Ich vermute nval steht für "new Value".
Zeile 4 ist Deine Vorbelegung von nval mit bsp. Ports="alter Wert"

Zeile 6 könnte im Durchlauf auch mal so aussehen:
if "Ports="=="Ports=" wenn das also gleich ist, dann ist es nicht sinnvoll in der Zeile drauf set nval=Ports=Ports= zu setzen.
Dort sollte dann set nval=Ports=TCPIP stehen.

Zeile 10: Du kannst nicht zeilenweise in die Datei schreiben, die Du gleichzeitig zeilenweise ausliest.
Schreib in eine neue Datei und ersetze damit die alte, wenn Du fertig bist.

Falls die user.dic Sonderzeichen wie z.B. <, >, ! und & enthält oder falls Leerzeilen vorkommen, die erhalten bleiben sollen, dann wird es etwas aufwändiger.


Zitat von @Hedgehogi:
Es kann manchmal so simpel sein...
...
Manchmal kann die Lösung so einfach sein...
Für wen?

Gruß Frank
Mitglied: Hedgehogi
Hedgehogi 19.05.2017 um 08:12:48 Uhr
Goto Top
Poste doch mal einen repräsentatives Inhaltsbeispiel, falls der (auch nach Zensierung) nicht zur privat ist.
Ein Auszug aus der Datei. Es ist komplett so aufgebaut.
DESIGNCACHE_MAX_SIZEKB=2000
InstallType=6
MINIMIZEONLOCKOUT=1
# Technote 1238346
ShowPreviewCollapsedInitially=1
ConfigFile=U:\Data\Setup.txt 
Timezone=-1
UserInterface=de
Setup=850300
Es sind immer Zeilen. Diese können auch ersetzt werden. Also wenn "Ports=" da steht, dies einfach mit Ports=TCPIP ersetzen. Falls es nicht vorkommt, soll es einfach eingefügt werden. Position ist egal.

Falls die user.dic Sonderzeichen wie z.B. <, >, ! und & enthält oder falls Leerzeilen vorkommen, die erhalten bleiben sollen, dann wird es etwas aufwändiger.
Es sind zwar Sonderzeichen drin, aber diese sollen nicht ersetzt werden.. Bzw. auch keine, die ersetzt werden müssen. Im Beispiel ist nun # Technote zu sehen. Bzw. der Config Pfad. Ist das ein Problem? An sich werden nach keinen Sonderzeichen gesucht.

Generell: Code schreibt man in einem Beitrag in code-Tags (siehe Formatierungen in den Beiträgen ).
Beim ersten Beitrag ging es durch die Hilfe. Hatte mich schon gewundert, warum beim Kommentieren diese nicht angezeigt wird. Gut, danke der Info.

Für wen?
Ich meine damit das Ergebnis. Mir ist klar, dass der Weg dahin steinig sein kann. Aber die Lösung ist manchmal dann doch simpel.

Viele Grüße
Mitglied: Pedant
Pedant 19.05.2017 um 12:53:00 Uhr
Goto Top
Hallo Hedgehogi,

Zitat von @Hedgehogi:
Es sind immer Zeilen. Diese können auch ersetzt werden. Also wenn "Ports=" da steht, dies einfach mit Ports=TCPIP ersetzen. Falls es nicht vorkommt, soll es einfach eingefügt werden. Position ist egal.
Die Anforderung "Falls es nicht vorkommt, soll es einfach eingefügt werden" ist neu, aber egal.
Da Du geschrieben hast, dass die Position egal wäre, füge ich diese Zeilen einfach pauschal hinten an und verwerfe später die alten Zeilen, falls sie schon verhanden waren.

Zitat von @Hedgehogi:
Es sind zwar Sonderzeichen drin, aber diese sollen nicht ersetzt werden.. Bzw. auch keine, die ersetzt werden müssen. Im Beispiel ist nun # Technote zu sehen. Bzw. der Config Pfad. Ist das ein Problem?
Bei meinem Kommentar bezüglich Sonderzeichen ging es darum, dass diese in Variablen und deren Ausgabe per echo durchaus eine Sonderbehandlung benötigen können.
# Technote ist ein Sonderfall, da diese Zeile kein = enthält.
Der Config Pfad stellte sich nicht als Problem herraus.

@echo off

set dateiorg=user.dic
set dateiin=input.txt
set dateiout=output.txt
if exist %dateiout% del %dateiout%

echo(
echo Konvertiere:
echo Von : %dateiin%
echo Nach: %dateiout%
echo(

REM Input-Datei erzeugen und erforderliche Zeilen anfügen
copy %dateiorg% %dateiin%
>>%dateiin% echo(
>>%dateiin% echo(Ports=neuezeile
>>%dateiin% echo(Setup=neuezeile
>>%dateiin% echo(InstallMode=neuezeile
>>%dateiin% echo(InstallType=neuezeile

for /f "tokens=1,* delims==" %%a in ('type "%dateiin%"') do (  
  if "%%b" == "" echo in : %%a  
  if not "%%b" == "" echo in : %%a=%%b  
  call:ausgabe "%%a" "%%b"  
)

:aufraeumen
REM del %dateiorg%
REM del %dateiin%
REM ren %dateiout% %dateiorg%
goto :eof

:ausgabe
set zeile=%~1=%~2
echo zl : %zeile%
if "%~1" == "Cache"       echo out:  - drop line -  
if "%~1" == "Cache"       goto :eof  
if "%~1" == "Desktop"     echo out:  - drop line -  
if "%~1" == "Desktop"     goto :eof  

REM bei # Technote 1238346 ist kein "=" dabei, daher ist %2 leer  
if "%~2" == ""            set zeile=%~1  

if "%~1" == "Ports" (  
  if "%~2" == "neuezeile" (  
    set zeile=Ports=TCPIP
  ) else (
    echo out:  - drop line -
    goto :eof
  )
)
if "%~1" == "Setup" (  
  if "%~2" == "neuezeile" (  
    set zeile=Setup=900100
  ) else (
    echo out:  - drop line -
    goto :eof
  )
)
if "%~1" == "InstallMode" (  
  if "%~2" == "neuezeile" (  
    set zeile=InstallMode=0
  ) else (
    echo out:  - drop line -
    goto :eof
  )
)
if "%~1" == "InstallType" (  
  if "%~2" == "neuezeile" (  
    set zeile=InstallType=8
  ) else (
    echo out:  - drop line -
    goto :eof
  )
)
echo out: %zeile%
>>%dateiout% echo(%zeile%
goto :eof
Ich habe einige Echos zum Debuggen drin, die Du rauswerfen kannst, wenn's fertig ist.

In einer vollständigen user.dic können durchaus noch Sonderfälle vorkommen, die noch nicht berücksitigt sind.
Mit denen wünsche ich Dir viel Vergnügen.

Gruß Frank
Mitglied: Hedgehogi
Hedgehogi 19.05.2017 um 16:30:46 Uhr
Goto Top
Hallo,

ich habe mich an einer Variante versucht und bin dabei auf 2 Probleme gestoßen:
1. Es ist wirklich sehr langsam das kopieren. Geht dies auch schneller? Ich habe es gerade geschnallt.. ich durchlaufe die Datei mehrmals und kopiere diese... auch nicht super...
2. "Directory" kopiert er nicht den Pfad, bzw. ersetzt ihn. Woran könnte das liegen?

Vielen Dank für deine Variante. Ich werde diese mal ebenfalls ausprobieren.

FOR %%i IN ("Ports=" "Setup=" "TemplateSetup=" "DISABLE_CLIENTRECORD=" "CreateDatabases=" "UpdateDS=" "LCREATE=" "Directory=U:\TOOL\Data=" "SharedDataDirectory=" "MAX_SIZEKB=" "ConfigFile=" "DST=" "DSTLAW=" DO (  

	set suchwort=%%i

	IF !suchwort! equ "Ports=" set ersatzzeile=Ports=TCPIP  
	IF !suchwort! equ "Setup=" set ersatzzeile=Setup=850200  
	IF !suchwort! equ "TemplateSetup=" set ersatzzeile=TemplateSetup=850200  
	IF !suchwort! equ "DISABLE_CLIENTRECORD=" set ersatzzeile=DISABLE_CLIENTRECORD=0  
	IF !suchwort! equ "CreateDatabases=" set ersatzzeile=CreateDatabases=1  
	IF !suchwort! equ "UpdateDS=" set ersatzzeile=UpdateDS=1  
	IF !suchwort! equ "LCREATE=" set ersatzzeile=LCREATE=1   
	IF !suchwort! equ "Directory=" set "ersatzzeile=Directory=U:\TOOL\Data"  
	IF !suchwort! equ "SharedDataDirectory=" set ersatzzeile=SharedDataDirectory=I:\TOOL\Data\Shared  
	IF !suchwort! equ "MAX_SIZEKB=" set ersatzzeile=MAX_SIZEKB=2000  
	IF !suchwort! equ "ConfigFile=" set ersatzzeile=ConfigFile=I:\TOOL\Data\Setup.txt  
	IF !suchwort! equ "DST=" set ersatzzeile=DST=1  
	IF !suchwort! equ "DSTLAW=" set ersatzzeile=DSTLAW=3,-1,1,10,-1,1  
	
	FOR /F "delims=" %%j IN (%SCRIPT_LOCATION%testing.txt) DO (  
		echo %%j | Findstr /b !suchwort! >nul
		if Errorlevel 1 (
			echo %%j>>%temp%\new.txt
		) Else (
			echo !ersatzzeile!>>%temp%\new.txt
		)
	)
	move %temp%\new.txt %SCRIPT_LOCATION%testing.txt
)
Mitglied: Pedant
Pedant 19.05.2017 aktualisiert um 20:01:14 Uhr
Goto Top
Hallo Hedgehogi,

zu. 2.
In Deiner Suchwortliste (Zeile 1) steht "Directory=U:\TOOL\Data=", Du vergleichst in Zeile 12 aber nur mit "Directory=".

Zu 1.
Ja, Du durchläust die Datei mehrfach.
Die innere Schleife (Zeile 19) druchläuft jedes mal die komplette Datei
und bedingt durch die äußere Schleife (Zeile 1) mit 13 Suchworten wird die innere Schleife 13 mal druchlaufen.

Das mehrfache Durchlaufen lässt sich meines Erachtens nach nicht vollstängig vermeiden.
a) Du musst jede Zeile der Datei abhandeln
b) Du musst jedes Suchwort auf jede Zeile anwenden

Zu a) sehe ich keine Alternative.
Das mache ich auch so, allerdings in der äußeren Schleife, was vermutlich keinen Unterschied macht, weil
innen x außen = außen x innen

Bei b) könnte man aufhören zu suchen, sobald man einen Treffer hat, da alle weiteren Suchworte nicht mehr vorkommen.
Das habe ich ein Stück weit im ausgelagerten Funktionsblock :ausgabe schon gemacht, das wäre aber auch dort ausbaufähig.

CMD-For-Schleifen kennen leider kein continue mit dem man den aktuellen Druchlauf abbrechen könnte, um dadurch sofort zum nächsten Durchlauf zu kommen
Ein Funktionsblock, der mit call :sprungmarke aufgerufen wird, lässt sich vorzeitig abbrechen durch goto :eof und die Ausführung macht bei der nächsten Zeile unter dem call-Befehl weiter.


Nachtrag

In Zeile 22 und 24 schreibst Du Variablen per Umleitung der Ausgabe von echo in eine Datei.
Spätestens wenn Du nicht genau weißt was Du ausgibst, solltest Du die Umleitung an den Anfang der Zeile setzen, also nicht
echo %%j>>%temp%\new.txt
sondern
>>%temp%\new.txt echo %%j

echo test=2>>%temp%\new.txt funtioniert wie erwartet.
echo test = 2>>%temp%\new.txt funtioniert nicht wie vielleicht erwartet.
Das habe ich auch erst vor Kurzem gelernt und wird hier hier erklärt.

Gruß Frank
Mitglied: Hedgehogi
Hedgehogi 22.05.2017 aktualisiert um 09:20:38 Uhr
Goto Top
Hallo Frank,

vielen Dank für dein Feedback. Das bringt mich auf dem Weg der Erkenntnis wieder ein Stück weiter face-smile
Ich lese aus deiner Antwort heraus, dass mein Code nicht ganz so schlecht ist?!

Bei b) könnte man aufhören zu suchen, sobald man einen Treffer hat, da alle weiteren Suchworte nicht mehr vorkommen.
Das habe ich ein Stück weit im ausgelagerten Funktionsblock :ausgabe schon gemacht, das wäre aber auch dort ausbaufähig.

Danke für den Tipp, daran hatte ich jetzt garnicht gedacht. Das mache ich mal.

In Deiner Suchwortliste (Zeile 1) steht "Directory=U:\TOOL\Data=", Du vergleichst in Zeile 12 aber nur mit "Directory=".
Danke, hatte ich übersehen. Komisch ist nur, dass heute der Rest funktioniert, obwohl ich nichts geändert habe o.0

Dabei ist ein Problem trotzdem entstanden:

EDIT:
SPELL_DIR=C:\Program Files (X86)\Tools\Spell_Dir
Dort bricht das Script immer ab und sagt: "\Tools\Spell_Dir kann syntaktisch an dieser Stelle nicht verarbeitet werden"
Woran könnte das liegen? Liegt das an dem selben Namen? Oder an dem Unterstrich? Wie kann ich das umgehen?
Liegt das etwa an der Klammer? Mhhh,... wie bekommt man das zum "übersehen"...

Viele Grüße und einen schönen Start in die Woche.
Mitglied: Pedant
Pedant 22.05.2017 um 12:02:18 Uhr
Goto Top
Hallo Hedgehogi,

Zitat von @Hedgehogi:
SPELL_DIR=C:\Program Files (X86)\Tools\Spell_Dir
Dort bricht das Script immer ab und sagt: "\Tools\Spell_Dir kann syntaktisch an dieser Stelle nicht verarbeitet werden"
Woran könnte das liegen? Liegt das an dem selben Namen?
SPELL_DIR==C:\Program Files (X86)\Tools\Spell_Dir kommt in Deinem Code nicht vor und kann daher keine Probleme verursachen.
Der selbe Namen wie was?

Poste bitte vollständigen Code, was nicht heißt, dass Du all Deine Geheimnisse preisgeben sollst.
Aus "privates" und "geheimes" kannst Du gern "apfel" und "birne" machen.
Der Code muss auch nicht vollständig sein in Bezug auf Dein gesamtes Skript, sondern vollständig insofern, dass alle funktionellen und problemrelevant Zeilen vorhanden sind.
Beispielsweise fehlen bei Deinem letzten Code-Posting
  • set SCRIPT_LOCATION=C:\Temp\Test\
  • setlocal enableDelayedExpansion

Zitat von @Hedgehogi:
Ich lese aus deiner Antwort heraus, dass mein Code nicht ganz so schlecht ist?!
Das kann ich nicht wirklich beurteilen.
Wenn eine Batch ihren Zweck erfüllt und Fehlverhalten auszuschließen sind, ist sie gut.
Ob es dann auch eleganter ginge ist zweitrangig.
Deine geschachtelte For-Schleife ist soweit in Ordnung und ist potentiell in der Lage die gestellte Aufgabe zu erfüllen.

Mit Fehlverhalten mein ich vor allem, dass Quelldaten beschädigt oder "Unbeteiligte" gefährdet werden könnten.
Hier ein ersonnenes, schlimmes Beipiel:
cd Ordner=X:\xyz
cd /d %Ordner%
echo j | del *.*
Sollte set scheitern, sodass %Ordner% leer ist oder cd scheiten, weil %Ordner% gerade nicht verfügbar ist, so findet kein Verzeichniswechsel statt und es werden alle Dateien im aktuellen Ordner des aktuellen Laufwerks gelöscht. Ooops, schade.

Mit fiel gerade auf, dass hier eine schließende Klammer vor dem Do fehlt
FOR %%i IN ("Ports=" " ... "DST=" "DSTLAW=" DO (...
FOR %%i IN ("Ports=" " ... "DST=" "DSTLAW=") DO (...


Zitat von @Hedgehogi:
...obwohl ich nichts geändert habe o.0
Was bedeutet "o.0", "oder Null" oder was?

Gruß Frank
Mitglied: Hedgehogi
Hedgehogi 22.05.2017 um 13:22:16 Uhr
Goto Top
Hallo,

ich habe in meinem Code lediglich die folgende Zeile hinzugefügt:

...
IF !suchwort! equ "DSTLAW=" set ersatzzeile=DSTLAW=3,-1,1,10,-1,1  
IF !suchwort! equ "SPELL_DIR=" set ersatzzeile=SPELL_DIR=C:\Program Files (X86)\Tools\Spell_Dir  
			
FOR /F "delims=" %%j IN (%SCRIPT_LOCATION%testing.txt) DO (   
...
Hier wird der Fehler "\Tools\Spell_Dir" kann syntaktisch an dieser Stelle nicht verarbeitet werden." ausgegeben.
Ich habe soweit rausgebekommen, dass es wohl an den Klammern liegt. Aber ich habe noch keine brauchbare Lösung...

Habe ich ebenfalls drin:
SETLOCAL EnableDelayedExpansion

...obwohl ich nichts geändert habe o.0
Was bedeutet "o.0", "oder Null" oder was?
Eigentlich sollte es ein verwundertes Gesicht, bzw. Verwunderung ausdrücken. Mein Fehler.
Mitglied: Pedant
Pedant 22.05.2017 um 15:09:59 Uhr
Goto Top
Hallo Hedgehogi ,

kann gerade nicht Testen.

Versuch's mal mit ^(
IF !suchwort! equ "SPELL_DIR=" set ersatzzeile=SPELL_DIR=C:\Program Files ^(X86)\Tools\Spell_Dir
http://www.robvanderwoude.com/escapechars.php

Zitat von @Hedgehogi:
Eigentlich sollte es ein verwundertes Gesicht, bzw. Verwunderung ausdrücken. Mein Fehler.
Ach ja, die lieben Smilies oder auch Emotion-Dingda. Hätte ich denken können/sollen => Mein Fehler.

Gruß Frank
Mitglied: 132895
Lösung 132895 22.05.2017 aktualisiert um 15:13:01 Uhr
Goto Top
Anführungszeichen drum dann spielen Sonderzeichen etc. keine Rolle...
IF "!suchwort!" equ "SPELL_DIR=" set "ersatzzeile=SPELL_DIR=C:\Program Files (X86)\Tools\Spell_Dir"  
Mitglied: Hedgehogi
Hedgehogi 23.05.2017 aktualisiert um 14:09:40 Uhr
Goto Top
Das hat funktioniert, danke.
Ich hatte die Anführungsstriche falsch gesetzt... oh man.

Mir sind leider Gottes zwei Probleme aufgefallen, welches ich nicht kapiere:
Das kopieren, verschieben und bearbeiten funktioniert soweit.
Es wird durch die ersten Verzeichnisse gegangen und alles ausgeführt. Jetzt zeigt mir aber die Konsole bei meinen letzten beiden Testverzeichnissen (alle meine Tests sind Kopien von Originalen), dass ein Syntaxfehler vorliegt, obwohl die Datei user.bic bearbeitet wurde. Im Code wird die jeweilige Datei Zeile für Zeile nach den gewünschten Strings durchsucht und dann in eine Temp geschrieben. Zum Schluss wird die Temp in die jeweilige Datei verschoben: Alles scheint korrekt und trotzdem tritt der "Syntaxfehler" bei jedem "verschieben" auf.
FOR %%i IN("Ports=" "Directory=U:\TOOL\Data=" "ConfigFile=" "DST=" "DSTLAW=" DO (   

    IF !suchwort! equ "Ports=" set ersatzzeile=Ports=900100  
    ...
    IF !suchwort! equ "DSTLAW=" set ersatzzeile=DSTLAW=3,-1,1,10,-1,1   

    FOR /F "delims=" %%j IN (!pfad_nutzerkennung!\Backup\user.dic) DO (  
        echo %%j | Findstr /b /i !suchwort! >nul
	if Errorlevel 1 (
	    echo %%j>>%temp%\new.txt
	) Else IF !ersatzzeile! neq loeschen (
	    echo !ersatzzeile!>>%temp%\new.txt
	)
    )
    move %temp%\new.txt !pfad_nutzerkennung!\Backup\user.dic
)
Ich verstehe nicht, wieso bei zwei "Beispielen" Syntaxfehler ausgegeben, aber trotzdem alles korrekt bearbeitet wird...
In der Konsole steht:
Syntaxfehler.
1 Datei(en) verschoben

Wenn ihr einen besseren Vorschlag für die Performance habt, immer her damit. Weil das bearbeiten der user.dic verdammt lange dauert... Zufrieden bin ich damit nicht, dass ich da fabriziert habe.

Das Zweite Problem ist, dass ab und zu bei der aller ersten Bearbeitung der user.bic auf einmal Code von einer anderen willkürlichen user.bic auftaucht.
Das heisst, das erste Nutzerverzeichnis ist z.B. Nutzer0001. Diese Nutzerverzeichnise werden folgendermaßen aus dem Beispiel von Pendant im folgenden Code durchlaufen. Das kuriose ist, dass z.B. in der user.bic dann ein Stück Textinhalt aus Nutzer0002 auftaucht. Bei allen anderen Dateien funktioniert die Bearbeitung wie gewünscht.
...
set pfad_ohne_nummer=C:\Temp\Test\Nutzer 
set /a zaehler=0 
:wiederholung 
REM zaehler um 1 erhöhen 
set /a zaehler+=1 

if %zaehler% lss 10 ( 
  set pfad_mit_nummer=%pfad_ohne_nummer%000%zaehler% 
  goto kopieren 
) 
if %zaehler% lss 100 ( 
...

if not exist %pfad_nutzerkennung%\. (
	goto wiederholung
)

pushd "%pfad_nutzerkennung%"  
FOR /F %%i IN ('dir /s /b user.dic, bookmark.txt, *.id ^| find /v "Backup"') DO (  

set var=%%i

	REM Prüfen, ob von allen Dateien eine bookmarks.id vorhanden ist. Diese soll nicht kopiert werden.
	if NOT !var:~-13!==booksmarks.id (
		xcopy /Y "%%i" "%pfad_nutzerkennung%\Backup\"  
	)
	REM user.dic soll bearbeitet werden.
	if !var:~-8!==user.dic (

Hier wird dann der Code von Oben genommen, welcher die user.dic bearbeitet.
Ich verstehe also nicht, wie das Batch Script überhaupt auf die Idee kommt, die erste user.dic mit Code von einer anderen zu befüllen?!... ich kann das leider nicht nachvollziehen, da die Verzeichnisse Schritt für Schritt durchlaufen werden...

Ich habe das Gefühl, dass Batch sehr gerne macht, was es will, oder?!... manche Fehler sind einfach nicht nachzuvollziehen. Oder könnt ihr mir einen vernünftigen Debugger empfehlen, mit dem man das eigene Script debuggen kann?
Mitglied: Pedant
Pedant 23.05.2017 um 16:26:26 Uhr
Goto Top
Hallo Hedgehogi,

Deine Codeausschnitte sind zu unvollständig um da sinnvoll etwas nachzuvollziehen.
Wie und wo wird %pfad_nutzerkennung% belegt?
Wo findet das popd zum pushd statt?
...
Wäre es denn tatsächlich zu indiskret das komplette Skript zu posten?
Schön wäre auch eine möglichst vollständige Ausgabe von dir /s /b U:\Nutzer00001 zu sehen, damit man mal weiß womit Du es zu tun hast und sich eine geeignete Testquelle basteln kann.

Ganz allgemein, Du könntest auch erst in einer Schleife für alle Ordner das Kopieren durchführen und danach in einer neuen Schleife das Ändern der user.dic-Dateien.
Vielleicht ist das übersichtlicher und damit weniger fehlerträchtig.

Noch allgemeiner,
viel einfacher wäre Deine Aufgabe, wenn Du nicht die individuellen Backup unbedingt als Unterordner der Quellordner haben musst, dessen Sinn sich mir ohnehin gänzlich verschließt.
Lägen Quelle und Ziel auf anderen Laufwerken, könntest Du ohne Fallunterscheidungen und Schleifen das Kopieren per xcopy erledigen und per /exclude sehr selektiv sein.
Wenn die Sicherung erledigt ist, kann Du anschließend und unabhängig die Änderungen an den Zieldateien ausführen.

Zitat von @Hedgehogi:
...könnt ihr mir einen vernünftigen Debugger empfehlen, mit dem man das eigene Script debuggen kann?
Den gibt es nicht, weder in vernünftig noch in unvernünftig.
Was bleibt sind REM und echo im Code.

Gruß Frank
Mitglied: Hedgehogi
Hedgehogi 24.05.2017 um 12:24:14 Uhr
Goto Top
Hallo,

erst einmal danke für die Tipps,

ich habe meine beiden Problem Identifizieren und lösen können.

Problem 1:
In der ersten Kopie von user.bic und deren Bearbeitung kamen Daten aus den anderen user.bic`s vor.

Die Lösung des Problems war eigentlich relativ "einfach". Nachdem es mir später wie Schuppen von den Augen fiel:
Beim Bearbeiten der jeweiligen user.bic wird bei mir eine %temp% angelegt und dort alle Informationen hinterlegt. Dummerweise habe ich am Anfang vergessen zu prüfen, ob diese beim starten des Scripts existiert. Und wenn nun Informationen vom letzten Durchlauf drin sind, wurden diese in die erste user.bic übertragen. Blöd gelaufen...

...
IF !suchwort! equ "Ports=" set ersatzzeile=Ports=900100   
If exist %temp%\new.txt del %temp%\new.txt
If errorlevel 1 echo FEHLER: Löschen der temp Datei fehlgeschlagen.>>%LOG_LOCATION%log.txt
FOR /F "delims=" %%j IN (!pfad_nutzerkennung!\Tools\user.bic) DO (  
	if "%%j" neq "QuotePrefix=>" (  
		echo %%j | Findstr /b /i !suchwort! >nul
		if Errorlevel 1 (
			echo %%j>>%temp%\new.txt
		) Else IF !ersatzzeile! neq loeschen (
			echo !ersatzzeile!>>%temp%\new.txt
			if errorlevel 1 echo FEHLER: Kopieren der Zeile %%j fehlgeschlagen.>>%LOG_LOCATION%log.txt
		)
	)
)

Problem 2:
Syntatxfehler in der Konsole und trotzdem korrekt kopiert.

Das Problem lag an der user.bic. In zwei Beispieldateien war folgender Inhalt: QuotePrefix=>
Dadurch ist immer wieder ein Syntaxfehler an folgender Codestelle entstanden:
echo %%j | Findstr /b /i !suchwort! >nul

Ich habe das erstmal so gelöst:
...
FOR /F "delims=" %%j IN (!pfad_nutzerkennung!\Backup\user.bic) DO (   
    if "%%j" neq "QuotePrefix=>" (   
        echo %%j | Findstr /b /i !suchwort! >nul 
...

Ich schließe diesen String einfach aus. Kann man das eventuell besser lösen? Bzw. vielleicht in die Zeile echo %%j | Findstr /b /i !Suchwort! >nul integrieren? Oder wäre das eine schlechte Variante?

Ich hätte noch eine Frage: Die Performance beim Text bearbeiten ist grauenvoll. Ginge das irgendwie besser? Momentan mache ich das folgendermaßen:
FOR %%i IN ("#" "Ports=" "Directory=" "ConfigFile=" "DST=" "DSTLAW=" DO (   
    IF !suchwort! equ "Ports=" set ersatzzeile=Ports=900100  
    IF !Suchwort! equ ... 

    If exist %temp%\new.txt del %temp%\new.txt
    If errorlevel 1 echo FEHLER: Löschen der temp Datei fehlgeschlagen.>>%LOG_LOCATION%log.txt
    FOR /F "delims=" %%j IN (!pfad_nutzerkennung!\Backup\user.bic) DO (  
	    if "%%j" neq "QuotePrefix=>" (  
		    echo %%j | Findstr /b /i !suchwort! >nul
		    if Errorlevel 1 (
			    echo %%j>>%temp%\new.txt
		    ) Else IF !ersatzzeile! neq loeschen (
 			    echo !ersatzzeile!>>%temp%\new.txt
			    if errorlevel 1 echo FEHLER: Kopieren der Zeile %%j fehlgeschlagen.>>%LOG_LOCATION%log.txt
		    )
        	)
    )
    move %temp%\new.txt !pfad_nutzerkennung!\Backup\user.bic
)

viel einfacher wäre Deine Aufgabe, wenn Du nicht die individuellen Backup unbedingt als Unterordner der Quellordner haben musst, dessen Sinn sich mir ohnehin gänzlich verschließt.

Es ist mir klar, wo das Problem liegt, aber so liegt momentan die Aufgabe. Ich glaube, darum brauch man sich hier nicht den Kopf zerbrechen face-smile

Den gibt es nicht, weder in vernünftig noch in unvernünftig. Was bleibt sind REM und echo im Code.
Ist ja nicht gerade eine prickelnde Aussicht... Ich habe zwar "TakeCommand" gefunden, aber der hat mich bis jetzt nicht überzeugt. Und dazu nur eine 30 Tage Version.

Schon mal vielen Dank für die kompetente Unterstützung bei meinen Problemen. An sich läuft das Script ohne Probleme. Nur die Performance würde ich irgendwie verbessern wollen.

Viele Grüße
Mitglied: Pedant
Pedant 28.05.2017 um 11:40:41 Uhr
Goto Top
Hallo Hedgehogi,

Zitat von @Hedgehogi:
Die Performance beim Text bearbeiten ist grauenvoll.

ohne kompletten Code und ohne eine komplette Beispiel user.dic kann unsererseits nur geraten und nicht getestet werden.

Vielleicht ist es (etwas) schneller, wenn Du nicht die externe findstr.exe nutzt, sondern den String direkt mit der Variabelen vergleichst?

Statt
if "%%j" neq "QuotePrefix=>" (
   echo %%j | Findstr /b /i !suchwort! >nul
   if Errorlevel 1 (
das hier
if "%%j" == "!suchwort:~0,8!" (
Falls die Suchworte sich anhand der ersten 8 Zeichen eindeutig identifizieren lassen.
Mit der Methode wäre %%j in Anführungszeichen gesetzt und "QuotePrefix=>" kein Syntax-Problem mehr, was dessen Abfrage vorab, entbehrlich machen würde.

Der Flaschenhals ist aber vermutlich das zeilenweise Schreiben in die Textdatei %temp%\new.txt.
Wo liegt die Datei eigentlich, lokal oder im Netzwerk? (Bei %temp% hoffentlich lokal.)
Vieleicht bringt es auch was die jeweilige user.dic vor dem Auslesen nach %temp% zu kopieren, statt sie mehrfach von U:\Nutzer...\ zu lesen.

Gruß Frank
Mitglied: Hedgehogi
Hedgehogi 29.05.2017 aktualisiert um 10:48:33 Uhr
Goto Top
Guten Morgen Pedant,

Falls die Suchworte sich anhand der ersten 8 Zeichen eindeutig identifizieren lassen.
Da "Ports=" lediglich 6 Zeichen besitzt und einige andere Suchworte "doppelt" vorkommen, wird dieser einfache Vergleich von 8 Buchstaben nichts. "Ports=" hat 6, also müsste ich nach 6 Suchen. Genauso wie bei "Setup=" Oder sollten diese beiden einfach in einer if Bedingung mit 6 Zeichen gesucht werden?

Wo liegt die Datei eigentlich, lokal oder im Netzwerk? (Bei %temp% hoffentlich lokal.)
lokal

Ich würde ein präpariertes Beispiel gerne schicken wollen. Geht es hier? Weil das Posten möchte ich nicht.

Vielleicht eine andere Frage / Lösungsidee:
Da meine erste Idee das Dokument Zeilenweise durchläuft und die Ergebnisse in die Temp schreibt, könnte man dann nicht einfach die user.bic Zeilenweise durchlaufen und die Zeile direkt überschreiben? Dann erspart man sich das rüber kopieren / ersetzen.

Viele Grüße
Mitglied: Pedant
Lösung Pedant 29.05.2017 um 14:22:27 Uhr
Goto Top
Hallo Hedgehogi,

Zitat von @Hedgehogi:
Falls die Suchworte sich anhand der ersten 8 Zeichen eindeutig identifizieren lassen.
Da "Ports=" lediglich 6 Zeichen besitzt und einige andere Suchworte "doppelt" vorkommen, wird dieser einfache Vergleich von 8 Buchstaben nichts. "Ports=" hat 6, also müsste ich nach 6 Suchen. Genauso wie bei "Setup=" Oder sollten diese beiden einfach in einer if Bedingung mit 6 Zeichen gesucht werden?
Wenn das nicht so eindeutig ist, dann lass das weg, bevor Du Dich in Fallunterscheidungen verstrickst.

Zitat von @Hedgehogi:
Vielleicht eine andere Frage / Lösungsidee:
Da meine erste Idee das Dokument Zeilenweise durchläuft und die Ergebnisse in die Temp schreibt, könnte man dann nicht einfach die user.bic Zeilenweise durchlaufen und die Zeile direkt überschreiben? Dann erspart man sich das rüber kopieren / ersetzen.
Das Ersetzen innerhalb der Quelldatei geht mit cmd nicht.

Zitat von @Hedgehogi:
Ich würde ein präpariertes Beispiel gerne schicken wollen. Geht es hier? Weil das Posten möchte ich nicht.
Was mag wohl noch Geheimes in einem präparierten Beispiel stehen?
Du könntest mir etwas per E-Mail schicken (Adresse findest Du auf meiner Homepage),
allerdings möchte ich eigentlich Nichts erhalten, auf das ich hier keinen Bezug nehmen darf und diesen Thread dann per PN oder E-Mail fortzusetzen ist nicht der Sinn eines Forums.


Ich hab den Suchen/Ersetzen-Teil hier nochmal anders geschrieben.
1. Lies die Quelle zeilenweise
2. Prüf die Zeile und ändere sie falls erwünscht
3. Schreib die Zeile (in eine neue Datei), falls sie nicht verworfen werden soll.

Batchdatei
@echo off
setlocal enableDelayedExpansion
If exist new.txt del new.txt

FOR /F "tokens=1,* delims==" %%j IN (user.dic) DO (  

	set zeile=%%j=%%k
	set zeilenanfang=%%j

	REM Sonderfall: Zeile beginnt mit # und enthält kein = als delim,
	REM             daher muss das erzeugte = am Ende von zeile wieder entfernt werden.
	IF "!zeilenanfang:~0,1!" EQU "#"               set zeile="!zeile:~0,-1!"  

	IF "!zeilenanfang!" EQU "ConfigFile"           set zeile="ConfigFile=I:\TOOL\Data\Setup.txt"  
	IF "!zeilenanfang!" EQU "CreateDatabases"      set zeile="CreateDatabases=1"  
	IF "!zeilenanfang!" EQU "Directory"            set zeile="Directory=U:\TOOL\Data"  
	IF "!zeilenanfang!" EQU "DISABLE_CLIENTRECORD" set zeile="DISABLE_CLIENTRECORD=0"  
	IF "!zeilenanfang!" EQU "DST"                  set zeile="DST=1"  
	IF "!zeilenanfang!" EQU "DSTLAW"               set zeile="DSTLAW=3,-1,1,10,-1,1"  
	IF "!zeilenanfang!" EQU "LCREATE"              set zeile="LCREATE=1"  
	IF "!zeilenanfang!" EQU "MAX_SIZEKB"           set zeile="MAX_SIZEKB=2000"  
	IF "!zeilenanfang!" EQU "Ports"                set zeile="Ports=TCPIP"  
	IF "!zeilenanfang!" EQU "Setup"                set zeile="Setup=850200"  
	IF "!zeilenanfang!" EQU "SharedDataDirectory"  set zeile="SharedDataDirectory=I:\TOOL\Data\Shared"  
	IF "!zeilenanfang!" EQU "SPELL_DIR"            set zeile="SPELL_DIR=C:\Program Files (X86)\Tools\Spell_Dir"  
	IF "!zeilenanfang!" EQU "TemplateSetup"        set zeile="TemplateSetup=850200"  
	IF "!zeilenanfang!" EQU "UNSINN"               set zeile=  
	IF "!zeilenanfang!" EQU "UpdateDS"             set zeile="UpdateDS=1"  

	IF "!zeile!" NEQ "" (  
		set zeile=!zeile:"=!  
		>>new.txt echo !zeile!
	)
)
start notepad new.txt

user.dic
ConfigFile=X:\Temp\Test.txt
CreateDatabases=ändern
DESIGNCACHE_MAX_SIZEKB=2000
Directory=X:\Data
DISABLE_CLIENTRECORD=1
DST=0
DSTLAW=
InstallType=6
LCREATE=1
MAX_SIZEKB=5
MINIMIZEONLOCKOUT=1
Ports=UDP
QuotePrefix=>
Setup=0815
SharedDataDirectory=X:\Temp
ShowPreviewCollapsedInitially=1
SPELL_DIR=C:\Program Files (X86)\Test
# Technote 1238346
TemplateSetup=0815
Timezone=-1
UNSINN=WEG DAMIT
UpdateDS=0
UserInterface=de

new.txt
ConfigFile=I:\TOOL\Data\Setup.txt
CreateDatabases=1
DESIGNCACHE_MAX_SIZEKB=2000
Directory=U:\TOOL\Data
DISABLE_CLIENTRECORD=0
DST=1
DSTLAW=3,-1,1,10,-1,1
InstallType=6
LCREATE=1
MAX_SIZEKB=2000
MINIMIZEONLOCKOUT=1
Ports=TCPIP
QuotePrefix=>
Setup=850200
SharedDataDirectory=I:\TOOL\Data\Shared
ShowPreviewCollapsedInitially=1
SPELL_DIR=C:\Program Files (X86)\Tools\Spell_Dir
# Technote 1238346
TemplateSetup=850200
Timezone=-1
UpdateDS=1
UserInterface=de


Das finde ich wesentlich gradliniger und kommt ohne geschachtelte For-Schleifen aus.
Eventuell ist es sogar performanter.

Gruß Frank
Mitglied: Hedgehogi
Hedgehogi 29.05.2017 aktualisiert um 16:43:07 Uhr
Goto Top
Hallo,

es FUNKTIONIERT endlich. Vielen Dank für die Hilfe.

Jedoch hatte dein Beispiel bei mir irgendwie nicht ganz funktioniert. Ich musste folgende Zeilen (ab 08.) anpassen. Erst dann hatte das Script die Zeilen in der Datei geändert:
FOR /F "tokens=1,* delims==" %%j IN (user.dic) DO (  
			
			set zeile=%%j=%%k 
			set zeilenanfang=%%j 
			
			IF "!zeilenanfang:~0,1!" EQU "#" set zeile=  
			IF "!zeilenanfang:~0,7!" EQU "[Notes]" set zeile="[Notes]"  
			if "%%j" equ "Ports" set zeile="Ports=TCPIP"  
			if "%%j" equ "Setup" set zeile="Setup=900100"  
                      ...

Ich selbst habe viel gelernt und wie empfindlich Batch Scripte sein können...
Hätte ich es mit !Zeilenanfang! gelassen, ging das Script komischerweise nicht in das IF rein. Vielleicht kann man mich da noch aufschlauen.
Ich habe festgestellt, dass Batch Script sehr empfindlich sind. Das war für mich auch eine schwere Geburt, da halbwegs hinter zu steigen. Dank deiner Hilfe ist es tip top.
Mitglied: Pedant
Lösung Pedant 29.05.2017 um 18:23:46 Uhr
Goto Top
Hallo Hedgehogi,

Zitat von @Hedgehogi:
Hätte ich es mit !Zeilenanfang! gelassen, ging das Script komischerweise nicht in das IF rein. Vielleicht kann man mich da noch aufschlauen.
Hättest Du ein Beispiel gepostet, das nicht funktioniert, könnte ich Dir wahrscheinlich sagen warum das so ist.

Da Zeile 6 + 7
IF "!zeilenanfang:~0,1!" EQU "#" set zeile=irgendwas
zu funktionieren scheint,
ist es merkwürdig wenn es in Zeile 8
IF "!zeilenanfang!" EQU "Ports" set zeile=irgendwas
nicht funktioniert.

setlocal enableDelayedExpansion hast Du im Skript drin, oder?
(Ohne würden die Zeilen 6 + 7 auch nicht funktionieren.)

Wenn das Skript nicht in das IF reingeht kann das zwei Gründe haben:
1. Die Zeile wird gar nicht ausgeführt.
2. Die If-Bedingung ist nicht erfüllt.
In dem Fall ist 1. eher unwahrscheinlich.

Füg doch mal in Zeile 5 das hier zur Kontrolle ein:
echo Zeile: "!zeilenanfang!" / "%%j" / "!zeile!"
Das sollte dann sowas ausgeben:
Zeile: "Ports" / "Ports" / "Ports=TCPIP"

Vielleicht hattest Du auch einfach einen Fehler drin, wie beispielsweise "!zeilenanfang"! statt "!zeilenanfang!".

Gruß Frank
Mitglied: Hedgehogi
Hedgehogi 30.05.2017 aktualisiert um 10:01:41 Uhr
Goto Top
Problem erkannt, Problem aber noch nicht ganz verstanden , wieso das Auftritt:
FOR /F "tokens=1,* delims==" %%j IN (user.dic) DO (  
	set zeile=%%j=%%k
	set zeilenanfang=%%j
			
	IF "!zeilenanfang:~0,1!" EQU "#" set zeile=  
	echo Zeile: "!zeilenanfang!" / "%%j" / "!zeile!"  
	if "%%j" equ "Ports" set zeile="Ports=TCPIP"  
	if "%%j" equ "Setup" set zeile="Setup=900100"  
Die Ausgabe zeigt:
Zeile: "Ports " / "Ports" / "Ports=TCPIP "
Es sind Leerzeichen drin und deshalb konnte der String Vergleich nicht funktionieren.
Und wenn ich %%j nehme, ist ja der String ohne Leerzeichen.

EDIT:
... es war ein Leerzeichen hinter dem Folgenden Code:
"set zeile=%%j=%%k "
"set zeilenanfang=%%j "
Oh man.... nagut. Es funktioniert alles tadellos. Auch wenn ich es komisch finde, dass Batch da so penibel ist, hinter dem Code das Leerzeichen noch zu lesen.
Vielen Dank nochmal für die Tipps und Hilfen. Finde das Forum sehr Interessant. Hatte mal auch in anderen Beträgen rumgeschaut, welche unten aufgelistet werden.
Mitglied: Pedant
Pedant 30.05.2017 um 10:43:18 Uhr
Goto Top
Hallo Hedgehogi,

Zitat von @Hedgehogi:
Auch wenn ich es komisch finde, dass Batch da so penibel ist, hinter dem Code das Leerzeichen noch zu lesen.

Wenn Du das schon penibel findest, dann versuch es mal mit einem Leerzeichen vor dem Gleichheitszeichen.
set fred = Feuerstein
echo Nachname: "%fred%"
Ausgabe:
Nachname: ""

Man könnte meinen, dass "Feuerstein" ausgegeben würde, aber tatsächlich ist es ganz anders.
Es ist nicht nur so, dass der Variablen der Wert " Feuerstein" zugewiesen wird, sondern auch die definierte Variable heißt "fred " und nicht "fred".

set fred = Feuerstein
echo Undefiniert: "%fred%"
echo Nachname   : "%fred %"
Ausgabe:
Undefiniert: ""
Nachname   : " Feuerstein"

Noch viel Spaß mit cmd
Gruß Frank
Mitglied: colinardo
colinardo 30.05.2017 aktualisiert um 18:28:24 Uhr
Goto Top
Servus,
da stellen sich mir wirklich die Nackenhaare wenn ich das Suchen und Ersetzen mit Batch hier sehe.
Mach es doch gleich mit einer modernen Skriptsprache mit der sich das vernünftig umsetzen lässt:

Kleines Beispiel mit Powershell:
$file = 'D:\testdatei.txt'  
# Such-Terms und Ersetzung definieren (Suchterm in Regex-Syntax)
$searchterms = @{
    '^IP=.*'='IP=10.100.100.12'  
    '^Server=.*'='Server=Testserver'  
}
# Inhalt einlesen
$content = gc $file
# alle Suchbegriffe durch Ihre Ersetzung ersetzen
$searchterms.GetEnumerator() | %{
    $content = $content  -replace $_.Key,$_.Value
}
$content | sc $file

Grüße Uwe
Mitglied: Hedgehogi
Hedgehogi 02.06.2017 um 09:12:51 Uhr
Goto Top
Hallo Uwe,

für einen Profi wie dich ist das sicherlich grausam. Kann ich komplett nachvollziehen. Aber auch für die kleinen Leute, die sich mit Scripten frisch auseinander setzen, ist das ein Erfolg, wenn es funktioniert face-smile

Aber danke für dein Beispiel. Ich wollte mich auch mal mit PowerShell auseinander setzen und könnte dies als Beispiel nutzen.