evinben
Goto Top

Die Eingabe aus der Zeile einer externen .txt-Datei lesen, Batch abarbeiten und die nächste Zeile lesen usw. bis alle Zeilen abgearbeitet wurden.

Hallo,
Ich beabsichtige eine Batch-Datei mit einer externen .txt-Datei zu steuern, in der folgende zwei Parameter (Beschreibung und der Name des Ordners, abgetrennt von einander mit Semikolon) auf mehreren Zeilen stehen:

Heute;DringendeAufgaben
Diese Woche;Aufgaben
Nächste Woche;Niedrige Priorität
usw.
usw.
...

Die Batch funktioniert soweit bei manueller Angabe: Nach dem Ausführen erscheinen nacheinander zwei „set /p“-Eingabeaufforderungen und die obigen beiden Werte aus einer Zeile werden jeweils einzeln eingegeben. Diese beiden Werte werden intern in der Batch-Datei als Variablen von verschiedenen Befehlszeilen verarbeitet.
Wie kann ich anstatt mit der bisherigen manueller Eingabe das neue Vorhaben so automatisieren, dass zuerst nur die erste Zeile gelesen wird und wenn die Batch fertig ist dann wieder zum Anfang gehen und die zweite Zeile aus der externen .txt-Datei lesen und so weiter? Also eigentlich genauso, wie es bei der manuellen Eingabe bisher funktioniert, aber mit dem wesentlichen Unterschied, dass die Eingabewerte von einer Liste gelesen werden sollen und die Batch soll natürlich erst dann aufhören, wenn alle Sätze in der .txt-Datei abgearbeitet wurden.
Alle Befehlszeilen mit einer FOR-Schleife umzustrukturieren wäre es für mich ein großer Aufwand, da es gründliche Veränderung der Batch-Datei voraussetzt. Ich habe es sogar versucht und aufgegeben, da es meine Kenntnisse mit der Verkettung von FOR-Befehle so dermaßen sprengt, dass ich es fast aufgegeben habe.

Danke sehr

Content-Key: 174078

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

Ausgedruckt am: 28.03.2024 um 20:03 Uhr

Mitglied: 60730
60730 03.10.2011 um 23:53:05 Uhr
Goto Top
moin evilben..

  • wie weit bist du denn schon mit der Briemlerschen Bauanleitung aus dem B Bereich?

Ich habe es sogar versucht und aufgegeben, da es meine Kenntnisse mit der Verkettung von FOR-Befehle so dermaßen sprengt, dass ich es fast aufgegeben habe.

Zu dem Thema gibt es ja hier auch fast nix, der Bastla schreibt ja genausowenig Schleifen wie Biber, Bietsch, Bubberman oder Briemler.
Ps: "Leider" ist mir beim scrollen das Trackpad verrutscht, der eine + Anspruchsvolle war ich, obwohl es zum jetzigen Zeitpunkt sehr unanspruchsvoll ist.

N8
Mitglied: evinben
evinben 04.10.2011 um 06:38:44 Uhr
Goto Top
Hallo TimoBeil,

nehmen wir an ich muss tatsächlich die betroffene Batch-Datei gründlich umstrukturieren. Mit so einer Befehlszeile, wie diese
 robocopy "%Quelle%\Boot" "%Ziehl%\boot" /MIR   
habe ich noch Schwierigkeiten sie in einer FOR-Schleife umzubauen. Ich zeige hier eine hoffnungsvolle Variante von meinen vielen Versuche:

PushD "%~dp0"  
for /f "usebackq tokens=1 delims=;" %%d in (Liste.txt) do set ErsteSpalte=%%d & for /f "usebackq tokens=2 delims=;" %%e in (Liste.txt) do (robocopy "%ErsteSpalte%" "%%e" /MIR)  
PopD

So funktioniert es aber leider nicht.

Bei anderen Befehlszeilen, ähnlich wie oben, muss ich wiederum aus der Ausgaben der ersten FOR-Schleife einen bestimmten Token an die zweiten FOR-Schleife weiterreichen. Wie soll nun dies umgesetzt werden? Meine Versuche, wie hier

PushD "%~dp0"  
for /f "usebackq tokens=2 delims=;" %%e in ('for /f "usebackq tokens=1 delims=;" %%d in (Liste.txt) do set ErsteSpalte=%%d') do robocopy "%ErsteSpalte%" "%%e" /MIR  
PopD

führen nur dazu, dass der Bach-Fenster sich blitzschnell schließt, ohne eine Fehlermeldung lesen zu können. Es ist echt zum Verzweifeln.

Es geht hier natürlich nicht nur um das Tool ROBOCOPY, sondern generell um das Prinzip. Dann kann ich zumindest anfangen und Schritt für Schritt alle betroffenen Befehlszeilen in "FOR-Schleifen" abzuändern.

Ich bin nach einer Woche mit der Batch endlich so weit fast fertig geworden und nun stelle ich fest, dass diese anders sei sollte, da die Eingabewerte viel einfacher aus einer txt-Datei eingelesen werden können. Nach einer Abfrage kann ich dann entscheiden, ob ich die Werte lieber manuell eingebe oder lieber aus einer externen txt-Datei einlesen lasse. Ich bin jedenfalls bereit zu lernen und werde, wenn es sein muss die Batch-Datei auf dem Kopf stellen und dort alles-alles ändern.

edit: obocopy=robocopy
Mitglied: bastla
bastla 04.10.2011 um 07:20:30 Uhr
Goto Top
Hallo evinben!

Tutorial zur FOR-Schleife ist ja nun wirklich nicht so gut versteckt ...

... anyhow: Wenn Du einfach darauf verzichtest, eigene Variablen für die Übergabe an "robocopy" zu verwenden und jene aus der Schleife nimmst (also auch "%%d"), sowie die Möglichkeit nutzt, mit zB "tokens=1-2" beide relevanten Werte in der gleichen Schleife auszulesen, solltest Du das schaffen ...

Grüße
bastla
Mitglied: mathe172
mathe172 04.10.2011 um 10:32:56 Uhr
Goto Top
Hallo,

vielleicht noch eine kleine Ergänzung zu den Beiträgen von Timo und Bastla:
Mehrzeilige Anweisungen in For-Schleifen (also alles in einer Schleife, und nicht wie du es, wenn ich das richtig interpretiere, machen wolltest) lassen sich so machen:
for /f "usebackq tokens=1,2 delims=;" %%A in ("Liste.txt") do (  
    REM Erste Anweisung
    REM Zweite Anweisung
)
...Oder, wenns komplexere Anweisungen sind (für manche ist es auch einfach übersichtlicher):
for /f "usebackq tokens=1,2 delims=;" %%A in ("Liste.txt") do call :Sub "%%A" "%%B"  
goto :eof

:Sub
robocopy "%~1" "%~2" /MIR  
REM ...
goto :eof

MfG,
Mathe172
[edit: Was das Blitzschnelle Schliessen des Batch Fensters angeht, dazu hat Timo sogar schon etwas in einem Tipp geschrieben ((at)echo off oder batch4runaways part 0.0000001
[edit: Nach einem Hinweis von Bastla "::" durch "REM" ersetzt]
Mitglied: 60730
60730 04.10.2011, aktualisiert am 18.10.2012 um 18:48:39 Uhr
Goto Top
Servus
Zitat von @mathe172:
[edit: Was das Blitzschnelle Schliessen des Batch Fensters angeht, dazu hat Timo sogar schon etwas in einem Tipp geschrieben
(

Ich hab mal einen TOC dazugemalt, jetzt muß der geneigte Tester nicht mehr den ganzen Text lesen - würde aber auch nichts schaden.
Ich muß den genannten Tipp eh mal aufhybschen. Aber danke für den Denkanstoss face-wink

Gruß
Mitglied: bastla
bastla 04.10.2011 um 13:05:13 Uhr
Goto Top
@mathe172

Getestet hast Du Dein erstes Code-Beispiel aber wohl nicht ...

... ansonsten hättest Du vermutlich "::" durch "rem" ersetzt ... face-wink

Grüße
bastla
Mitglied: mathe172
mathe172 04.10.2011 um 20:50:00 Uhr
Goto Top
Hallo,

Getestet hast Du Dein erstes Code-Beispiel aber wohl nicht ...
nein, hab ich nicht face-smile, aber wieso funktioniert das mit den :: eigentlich nicht? Hab ich da eine (andere) Programmiersprache hineingemischt?

MfG,
Mathe172
Mitglied: bastla
bastla 04.10.2011 um 21:37:08 Uhr
Goto Top
@mathe172
wieso funktioniert das mit den :: eigentlich nicht?
Da muss ich auch passen - ich wusste nur, dass ... face-wink

Grüße
bastla
Mitglied: evinben
evinben 05.10.2011 um 07:39:17 Uhr
Goto Top
danke euch alle wieder ganz herzlich für die treue Hilfe ;).

Das mit dem :SUB Aufruf winde ich genial. Wieder heute tolles gelernt.

1. Wenn ich richtig verstanden kann ich den Bereich :
( 
    REM Erste Anweisung 
    REM Zweite Anweisung 
)
wie folgt ausfüllen:
(
for /f "usebackq tokens=1,2 delims=;" %%A in ("Liste.txt") do  
for /f "usebackq tokens=2,3 delims=;" %%A in ("Liste.txt") do echo  %%A  
)

2. Sind "%~1", "%~2", "%~3" usw. Variablen der Variablen der davor stehenden Befehlszeile? Ist deren Vorteil zu den alphabetischen Variablen (%%a, %%b, %%c, usw.), mit denen ebenso eine exakte Sortierung analog zu den numerischen erreicht wird, nur eine Erleichterung was das Zählen betrifft?
Es muss ja ein Grund geben, warum anstatt
 ...... do call :Sub "%~1" "%~2"  
folgendes
 ...... do call :Sub "%%A" "%%B"  
verwendet wird, und warum anstatt ebenso wie in der davor stehenden Befehlszeile
 :Sub
 <Befehl> "%%A" "%%B"  
folgendes
 :Sub
*<Befehl> "%~1" "%~2"  
verwendet wird.

Am Mittwoch sollte die Arbeitskurve die höchste sein... Einen frischen Tag euch allen
Mitglied: bastla
bastla 05.10.2011 um 08:06:43 Uhr
Goto Top
Hallo evinben!
for /f "usebackq tokens=1,2 delims=;" %%A in ("Liste.txt") do
for /f "usebackq tokens=2,3 delims=;" %%A in ("Liste.txt") do echo %%A
ist nicht nur nicht (kannst und solltest Du aber nachholen) sondern auch nicht sinnvoll - Du kannst mit
for /f "usebackq tokens=1-3 delims=;" %%A in ("Liste.txt") do echo %%A_%%B_%%C
gleich alle 3 benötigten Werte am Stück auslesen und weiter verarbeiten ...
Kurz zu "%%A" vs "%1" (oder "%%~A" vs "%~1" = ohne ev umgebende Anführungszeichen):

In einer "for"-Schleife werden als Schleifenvariablen Buchstaben (ab dem ersten angegebenen - siehe oben: token1 = %%A, token2 = %%B, ...) verwendet.

Ein (mit "call" aufgerufenes) Unterprogramm verhält sich im Prinzip wie ein weiterer Batch und nimmt die beim Aufruf als Parameter übergebenen Werte als "%1" bis max "%9" an - daher Aufruf mit
call :Sub "%%A" "%%B"
und Übernahme der Inhalte von "%%A" und "%%B" als "%1" und "%2"
:Sub
echo %1 %2
echo %~1 und %~2
wobei in der ersten Ausgabe die Anführungszeichen an Anfang und Ende des Parameters erhalten und im zweiten Fall entfernt werden.

Grüße
bastla

[Edit] Fehlendes "~" in Zeile 3 ergänzt [/Edit]
Mitglied: evinben
evinben 05.10.2011 um 17:38:09 Uhr
Goto Top
alles ist nun klar Bastla!
Mit der Formatierung ist es kein Problem - ich ging davon aus, dass bei abgekürzten Angaben für den Leser es so - wie es war - übersichtlicher wäre. Ab nun werde ich alles formatieren, wenn die Regeln es verlangen.

ist nicht nur nicht als Code formatiert (kannst und solltest Du aber nachholen) sondern auch nicht sinnvoll - Du kannst mit
for /f "usebackq tokens=1-3 delims=;" %%A in ("Liste.txt") do echo %%A_%%B_%%C
gleich alle 3 benötigten Werte am Stück auslesen und weiter verarbeiten ...

Nein, kann ich so nicht. Es geht um solche Befehlszeilen:
Beim Ausführen der Batch werde ich nun nach der großen Batch- Umstrukturierung gefragt, ob die Infos manuell eingegeben oder lieber aus einer txt-Datei eingelesen werden sollen. Nun sollen die folgende Zeilen, wie die nachfolgenden beiden hier, geändert werden:
for /f "tokens=2 delims={}" %%i in ('bcdedit /store %Ziehl%\boot\bcd /create /d "%BootEintrag%" /application osloader') do set GUID={%%i}  
bcdedit /store %Ziehl%\boot\bcd /set %GUID% device "ramdisk=[boot]\%HauptOrdner2%\sources\boot.wim,{ramdiskoptions}"  

In der txt.Datei1 ist jeder GUID in ihrer Reihenfolge nach auf jeder Zeile zu finden. Damit die Werte aus den externen .txt-Dateien synchron eingelesen werden können, soll die Aufgabe jeweils auf einer Befehlszeile gepackt werden: die erste Befehlszeile muss den 2. Token (für Variable %BootEintrag%) aus der .txt-Datei2 einlesen; die zweite Befehlszeile muss nun von der .txt-Datei1 den 1. Token (für Variable %GUID%), und aus der txt-Datei2 den 1. Token (für Variable %HauptOrdner2%) einlesen.

Folgendes beinhaltet die txt-Datei2 (Beschreibung;Name des Haupt-Ordners):

Setup Windows Vista x32;Vista_x32
Setup Windows Vista SP1 x32;VistaSP1_x32
Setup Windows 7 SP1 x32;Win7SP1_x32
... usw.

Mein Kopf bricht bald zusammen, da ich nicht schaffe die beiden Befehlszeilen so umzuändern, dass die Werte aus den beiden externen .txt-Dateien synchron verarbeitet werden können.

Ich brauche etwas Pause, da ich mit %Null-Batch-Ahnung% in der letzten zwei Wochen für mich etwas zu heftige Batch geschrieben habe - d. h. es war für mich ein Crash-Kurs - jede Kleinigkeit kennenlernen, viele Lesen, und nicht nur kopieren und einfügen, sondern die Funktion verstehen, verdauen und probieren - probieren - probieren - probieren, sonst wäre ich überhaupt nicht vorwärts gekommen, bzw. hätte ich am liebsten hier im Forum in Echtzeit Fragen gestellt, die euch allen gelangweilt hätten.

Ich würde gerne die Batch posten, falls ihr nerven stabil seid - beruhigender weise funktioniert diese mit manueller Eingaben von zweier Werten. Für mich wäre natürlich das Wichtigste zu erfahren, wie so eine Aufgabe eigentlich korrekt zu lösen wäre, anstatt mit Code-Romanen.
Es wird somit ein Laufwerk für Multiboot vorbereitet.

Bis bald.
Mitglied: bastla
bastla 05.10.2011 um 17:44:04 Uhr
Goto Top
Hallo ebinben!
Ab nun werde ich alles formatieren, wenn die Regeln es verlangen.
Danke - es tut vor allem den Augen gut ... face-wink

Grüße
bastla
Mitglied: evinben
evinben 05.10.2011 um 18:48:52 Uhr
Goto Top
schön. Ich habe den Betrag etwas zu eilig fertig gestellt - nun habe ich ihn ergänzt.

GrußLa
Mitglied: bastla
bastla 05.10.2011 um 19:27:15 Uhr
Goto Top
Hallo evinben!

Dass 2 Textdateien involviert sein sollen ist ja mal was Neues - wobei ich in Deinen beiden Codezeilen keine einzige Datei erwähnt finde ...

Wenn es keinen Schlüssel gibt, anhand dessen die korrespondierende Zeile aus der anderen Datei gelesen werden kann, geht das eigentlich nur über die Zeilennummer - schematisch anhand der Dateien "Text1.txt" und "Text2.txt":
for /f "tokens=1* delims=:" %%i in ('findstr /n "^" "Text1.txt"') do for /f "tokens=1* delims=:" %%a in ('findstr /n "^" "Text2.txt"^|findstr /b "%%i:"') do echo %%j_%%b  
Durch die Verwendung zusätzlicher "tokens" und "delims" (für die Zeilennummer werden die dargestellten Werte 1. Token und Trennzeichen ":" - vgl die Ausgabe von
findstr /n "^" "Text1.txt"
- verwendet) können dann auch die jeweils benötigten Teile extrahiert werden.

Grüße
bastla
Mitglied: mathe172
mathe172 05.10.2011 um 20:47:43 Uhr
Goto Top
Hallo,

was das "korrekte" Lösen einer solchen Aufgabe angeht, hat Bastla wahrscheinlich schon das (annähernd) Perfekte gepostet.

Vielleicht noch eine Anmerkung zur Dateneingabe:
Am einfachsten sollte es so in der Art gehen
@echo off
REM Die Zeile ist nur da, damit man nur die set p Frage sieht und nicht alles. Erst einfügen wenn alles funktioniert
:Error
set /p Source="Sollen die Daten aus einer ^(D^)atei eingelesen werden oder werden sie ^(m^)anuell eingegeben? "  
if /i "%Source%"=="D" (  
REM For Schleife zum Abarbeiten der Datei mit [call :Sub "%%A" "%%B"] oder so  
goto :eof
)
if /i "%Source%"=="M" (  
REM Werte abfragen
REM Call :Sub "Wert1" "Wert2"  
goto :eof
)
goto :Error

:Sub
REM Meister Bastlas Code, vielleicht abgewandelt
REM Hier sind die Übergebenen Werte als Parameter zu behandeln
goto :eof

MfG,
Mathe172
Mitglied: bastla
bastla 05.10.2011 um 21:41:44 Uhr
Goto Top
@mathe172
... wobei ich auf die Zeilen 9 und 13 verzichten (wenn nicht Datei, dann eben manuell und gut ist - insbesondere auch ohne "delayedExpansion") und Zeile 14 auf
goto :eof
ändern würde ...

Falls tatsächlich noch die Überprüfung auf "M" gewünscht wäre, würde ich denSprung vorziehen und Zeile 9 so formulieren:
if /i "%Source%" neq "M" goto :Error
- Ergebnis: wieder keine "delayedExpansion" erforderlich ...

Grüße
bastla
Mitglied: mathe172
mathe172 06.10.2011 um 00:27:40 Uhr
Goto Top
@bastla
Stimmt natürlich, wie immer, das hab ich nicht so genau bedacht face-smile

Wobei sich natürlich die Frage stellt, ob es nicht sowieso einfacher ist, die Werte dann manuell abzufragen, wenn man keine Datei per Drag 'n Drop raufzieht. Damit hätte man einen Variablen Dateinamen und man könnte dem Benutzer eine Abfrage ersparen.
Ist aber sinnfrei, wenn die Datei nicht im selben Ordner ist face-wink

Aber was solche Fragen angeht, warten wir mal lieber auf den TO...

MfG,
Mathe172
[edit: Was DelayedExpansion in der Datei-Abfrage angeht, so fällt mir als einziger Grund für das Benötigen ein, dann man den Dateinamen abfragen will - wobei ich da dann Drag 'n Drop bevorzugen würde -->heisst also, Bastlas Vorschlag zeigt wieder mal den besten Weg face-smile]
Mitglied: evinben
evinben 06.10.2011 um 18:28:42 Uhr
Goto Top
danke euch wiedermal ganz herzlich. Es ist alles wie immer verständlich beschrieben/erklärt. Nun werden die angesprochenen Batch-Regelen in meinem Gehirn allmählich erleuchtet - es wird dankbar euch logischer und logischer. Ich brauche dennoch eine Pause - ein bisschen Sport und Ausgleich - und in zwei -drei Tagen dann wieder weiter.

Ich werde jedenfalls berichten. Sicherlich hat einer oder anderer das Interesse an so einem Multiboot-Projekt, an dem ich mehr aus Batch-Erfahrungsgründen als an dem Nutzen selbst, gearbeitet habe.

bis bald...