Komplette Ausgabe einer For -f Schleife in die gleiche Datei zurück
Hallo zusammen!
Dank diesem hilfreichen Tipp sind meine Versuche, kurze und effiziente Batches zu schreiben, meiner Meinung nach noch erfolgreicher geworden
Nun wurde in letzter Zeit mehrmals nach einem Skript gefragt, das eine Datei Zeilenweise verarbeitet und die Zeile bei Bedarf verändert. Das ganze soll wieder in der Ausgangsdatei landen...
Nun war mein Ansatz vereinfacht so:
Dieser Code sollte ja eigentlich jede Zeile von "Datei.txt" ausgeben und das alles wieder in die Datei schreiben.
Nun kommt aber die Fehlermeldung: Datei wurde nicht gefunden. -Seltsamerweise ist die Datei aber trotzdem leer, als ob die For-Schleife die Datei nicht findet, die Umleitung aber schon.
Da ich bis jetzt immer zu einer Temporären Datei gezwungen war, wollte ich wissen ob es an mir, der cmd.exe, der Programmunlogik oder am (wahrscheinlich) bekifften Programmierer liegt.
Vielleicht steht die Erklärung ja schon in dem oben genannten Beitrag und ich finde sie nicht.
Ich hoffe ihr wisst mehr
MfG,
Mathe172
Dank diesem hilfreichen Tipp sind meine Versuche, kurze und effiziente Batches zu schreiben, meiner Meinung nach noch erfolgreicher geworden
Nun wurde in letzter Zeit mehrmals nach einem Skript gefragt, das eine Datei Zeilenweise verarbeitet und die Zeile bei Bedarf verändert. Das ganze soll wieder in der Ausgangsdatei landen...
Nun war mein Ansatz vereinfacht so:
@echo off
::Gesamte Ausgabe der Schleife umleiten
(for /f "usebackq delims=" %%A in ("Datei.txt") do echo.%%A)>"Datei.txt"
Nun kommt aber die Fehlermeldung: Datei wurde nicht gefunden. -Seltsamerweise ist die Datei aber trotzdem leer, als ob die For-Schleife die Datei nicht findet, die Umleitung aber schon.
Da ich bis jetzt immer zu einer Temporären Datei gezwungen war, wollte ich wissen ob es an mir, der cmd.exe, der Programmunlogik oder am (wahrscheinlich) bekifften Programmierer liegt.
Vielleicht steht die Erklärung ja schon in dem oben genannten Beitrag und ich finde sie nicht.
Ich hoffe ihr wisst mehr
MfG,
Mathe172
Please also mark the comments that contributed to the solution of the article
Content-ID: 162713
Url: https://administrator.de/contentid/162713
Printed on: November 4, 2024 at 21:11 o'clock
12 Comments
Latest comment
Die Umleitung braucht die Datei nicht zu "finden", es legt sie schlicht und ergreifend an / überschreibt sie bei jedem Scriptdurchlauf.
Wie hattest du es dir bitte vorgestellt, zeilenweise Daten aus einer Datei auszulesen, die schon vor der Ausgabe der ersten Zeile wieder überschrieben wird (und damit 0 Inhalt hat)??
Wie hattest du es dir bitte vorgestellt, zeilenweise Daten aus einer Datei auszulesen, die schon vor der Ausgabe der ersten Zeile wieder überschrieben wird (und damit 0 Inhalt hat)??
@Highend01
Der Plan wäre es ja, zunächst (in der Klammer) alle Zeilen auszulesen und auszugeben, und erst danach die Ausgangsdatei mit dem "Gesamtergebnis" zu überschreiben (der Link Schleife ohne mehrmaliges Öffnen der Datei in welche Umgeleiteitet wird ist oben bei "diesem" leicht zu übersehen) ...
@mathe172
Wäre tatsächlich eleganter als das klassische
oder (leerzeilenbewahrend)
bzw
Grüße
bastla
[Edit] Fehlerhafte Schreibweise von "%temp%\Datei.txt" korrigiert [/Edit]
Der Plan wäre es ja, zunächst (in der Klammer) alle Zeilen auszulesen und auszugeben, und erst danach die Ausgangsdatei mit dem "Gesamtergebnis" zu überschreiben (der Link Schleife ohne mehrmaliges Öffnen der Datei in welche Umgeleiteitet wird ist oben bei "diesem" leicht zu übersehen) ...
@mathe172
Wäre tatsächlich eleganter als das klassische
move "Datei.txt" %temp%\Datei.txt
for /f "delims=" %%A in (%temp%\Datei.txt) do >>"Datei.txt" echo %%A
del %temp%\Datei.txt
move "Datei.txt" %temp%\Datei.txt
for /f "tokens=1* delims=:" %%A in ('findstr /n "^" %temp%\Datei.txt') do >>"Datei.txt" echo.%%B
del %temp%\Datei.txt
move "Datei.txt" %temp%\Datei.txt
(for /f "tokens=1* delims=:" %%A in ('findstr /n "^" %temp%\Datei.txt') do echo.%%B)>"Datei.txt"
del %temp%\Datei.txt
bastla
[Edit] Fehlerhafte Schreibweise von "%temp%\Datei.txt" korrigiert [/Edit]
@bastla
"und erst danach" beschreibt ja schon den eigentlichen Ansatz, das Ganze über eine temporäre Datei zu lösen. Dies wurde hier "vergessen" und deshalb funktioniert seine Herangehensweise ja auch nicht. Völlig unabhängig davon, ob er jetzt die Zieldatei immer neu geöffnet + geschrieben hätte (per >>) oder in einem Rutsch übertragen wollte
Du hast übrigens einen kleinen Schreibfehler in deinem Beispiel drin (nicht, dass es übernommen wird und dann die Frage gestellt wird, warum es nicht läuft):
"und erst danach" beschreibt ja schon den eigentlichen Ansatz, das Ganze über eine temporäre Datei zu lösen. Dies wurde hier "vergessen" und deshalb funktioniert seine Herangehensweise ja auch nicht. Völlig unabhängig davon, ob er jetzt die Zieldatei immer neu geöffnet + geschrieben hätte (per >>) oder in einem Rutsch übertragen wollte
Du hast übrigens einen kleinen Schreibfehler in deinem Beispiel drin (nicht, dass es übernommen wird und dann die Frage gestellt wird, warum es nicht läuft):
('findstr /n "^" %temp%\Datei.txt')
@Highend01
Danke für's genaue Hinsehen - ich korrigier's oben ...
Vielleicht schaust Du Dir aber trotzdem den verlinkten Tipp von PH an, um zu erkennen, was die Grundidee von mathes Ansatz war ...
Grüße
bastla
Danke für's genaue Hinsehen - ich korrigier's oben ...
Vielleicht schaust Du Dir aber trotzdem den verlinkten Tipp von PH an, um zu erkennen, was die Grundidee von mathes Ansatz war ...
Grüße
bastla
Zitat von @bastla:
Vielleicht schaust Du Dir aber trotzdem den verlinkten Tipp von PH an, um zu erkennen, was die Grundidee von mathes Ansatz war
Vielleicht schaust Du Dir aber trotzdem den verlinkten Tipp von PH an, um zu erkennen, was die Grundidee von mathes Ansatz war
Hatte ich getan. Deshalb hatte ich ja noch mal drauf geantwortet.
@mathe172
Weil deine Ein- und Ausgabedatei übereinstimmen. Verwende eine temporäre Datei für das Auslesen / alt. Schreiben.
Hallo,
so einfach ist es dann auch wieder nicht.
Genau genommen würde das Konstrukt von mathe0815 dazu führen, dass die Datei neu erzeugt wird, dann aber Zeile für Zeile die Daten angehängt werden.
Aber wie schon erkannt klappt das nicht.
Erstaunlicherweise scheint es an sich auch egal zu sein, dass sich der Inhalt der Datei ändert, die Datei scheint gecached zu werden!
Sprich, es können Daten gelesen werden die gar nicht mehr da sind.
Test mit
Nur leider klappt es eben nicht mehr, wenn man die ganze For-Schleife in einen Block packt.
Gruß
jeb
so einfach ist es dann auch wieder nicht.
Genau genommen würde das Konstrukt von mathe0815 dazu führen, dass die Datei neu erzeugt wird, dann aber Zeile für Zeile die Daten angehängt werden.
Aber wie schon erkannt klappt das nicht.
Erstaunlicherweise scheint es an sich auch egal zu sein, dass sich der Inhalt der Datei ändert, die Datei scheint gecached zu werden!
Sprich, es können Daten gelesen werden die gar nicht mehr da sind.
Test mit
@echo off
( for /l %%n in (1,1,3) do echo %%n) > t.txt
rem for %%a in (1) DO (
for /F "delims=" %%b in (t.txt) DO (
echo fileOut=%%b
>con echo aktuelle Zeile "%%b"
>con echo - Kompletter Inhalt von t.txt ----
>con type t.txt
>con echo - Datei ende ----
>con echo(
) > t.txt
--- OUTPUT ----
aktuelle Zeile "1"
- Kompletter Inhalt von t.txt ----
fileOut=1
- Datei ende ----
aktuelle Zeile "2"
- Kompletter Inhalt von t.txt ----
fileOut=2
- Datei ende ----
aktuelle Zeile "3"
- Kompletter Inhalt von t.txt ----
fileOut=3
- Datei ende ----
Nur leider klappt es eben nicht mehr, wenn man die ganze For-Schleife in einen Block packt.
Gruß
jeb
Moin,
ich weiss zwar nicht genau, was denn das erhoffte Einsparpotential sein soll, andererseits .... wird ja bestimmt für einen guten Zweck sein.
Und ist bestimmt besser, als irgendwo rumzuhängen...
Wieso findet ihr das Verhalten denn absonderlich?
Wenn eine Umleitung mit einer Pipe (also hier dem ">"-Zeichen) verlangt wird, dann wird zuerst das Ziel als Filehandle geöffnet,
und dabei eine 0-Byte-Datei im Verzeichnis angelegt, bevor überhaupt irgendeine Ausgabe zu schreiben ist.
Einfacher zum Nachvollziehen:
Im anderen Fenster macht ihr ein
...die Datei ist da, LANGE bevor da irgendein Output kommen könnte... die SLEEP.exe ist immer noch am Rumwarten.
Und dieses "Umleitungsziel wird zuerst angelegt"-Verhalten erklärt doch die Mathe-Frage zur Genüge, oder?
Wie sollte es denn auch anders sein?
Eine andere "Reihenfolge" wäre doch fatal.
Angenommen, eine 10-Gigabyte-Datei sollte per "type monsterlog.txt" umgeleitet werden auf "eineReadonlyDatei.txt".
Soll zuerst der "Type monsterlog.txt" vollständig durchrödeln, auch wenn er den Output im Ziel nicht schreiben kann?
Oder auch hier ein einfaches Beispiel:
[Das führende ">" gehört zum CMD-Prompt - nicht mit Eintippseln]
und er führt NICHT zuerst den kompletten DIR-Liste-mir-2-Millionen-Dateien-auf aus, sondern öffnet erst das Ziel "readonly.txt" oder verreckt.
Grüße
Biber
ich weiss zwar nicht genau, was denn das erhoffte Einsparpotential sein soll, andererseits .... wird ja bestimmt für einen guten Zweck sein.
Und ist bestimmt besser, als irgendwo rumzuhängen...
Wieso findet ihr das Verhalten denn absonderlich?
Wenn eine Umleitung mit einer Pipe (also hier dem ">"-Zeichen) verlangt wird, dann wird zuerst das Ziel als Filehandle geöffnet,
und dabei eine 0-Byte-Datei im Verzeichnis angelegt, bevor überhaupt irgendeine Ausgabe zu schreiben ist.
Einfacher zum Nachvollziehen:
- Macht einfach zwei CMD-Fenster auf, lasst beide im Standardverzeichnis stehen
- ruft in einem die Sleep.exe auf mit einem für Langsamtipper angemessenen Wert, z.B 20 oder 200 [sec] und leitet das Ergebnis um
sleep 20>sleeptest.txt
Im anderen Fenster macht ihr ein
dir sleept*.*
...
15.03.2011 22:41 0 sleeptest.txt
...die Datei ist da, LANGE bevor da irgendein Output kommen könnte... die SLEEP.exe ist immer noch am Rumwarten.
Und dieses "Umleitungsziel wird zuerst angelegt"-Verhalten erklärt doch die Mathe-Frage zur Genüge, oder?
Wie sollte es denn auch anders sein?
Eine andere "Reihenfolge" wäre doch fatal.
Angenommen, eine 10-Gigabyte-Datei sollte per "type monsterlog.txt" umgeleitet werden auf "eineReadonlyDatei.txt".
Soll zuerst der "Type monsterlog.txt" vollständig durchrödeln, auch wenn er den Output im Ziel nicht schreiben kann?
Oder auch hier ein einfaches Beispiel:
[Das führende ">" gehört zum CMD-Prompt - nicht mit Eintippseln]
>echo x >readonly.txt
(=22:57:03 D:\temp=)
>attrib readonly.txt +r
(=22:57:07 D:\temp=)
>dir c:\ /s /b >readonly.txt
Zugriff verweigert
Grüße
Biber
[OT]
@Biber
Grüße
bastla
[/OT]
@Biber
ich weiss zwar nicht genau, was denn das erhoffte Einsparpotential sein soll
... hybsch wär's gewesen (und da ja die 10-Gigabyte-Text-Dateien doch noch nicht soo überhandnehmen dürften, könnten sich die die paar GB RAM auch einmal nützlich machen) ...Grüße
bastla
[/OT]
[noch OTiger]
@bastla
Wenn meine geheimsten Hoffnungen in Erfüllung gehen...
und Karl Theodor zu Guttenberg tatsächlich Goldbärchens Nachfolger wird und "Wetten dass.." moderiert....
-> dann werde ich ihm ein paar Kandidaten nennen, die mit einer Querflöte 10 Schokopuddings in einer Minute durch einen Heuballen blasen können.
Oder zumindest ähnliches vorturnen .
Grüße zurück
Biber
[/noch OTiger]
@bastla
Wenn meine geheimsten Hoffnungen in Erfüllung gehen...
und Karl Theodor zu Guttenberg tatsächlich Goldbärchens Nachfolger wird und "Wetten dass.." moderiert....
-> dann werde ich ihm ein paar Kandidaten nennen, die mit einer Querflöte 10 Schokopuddings in einer Minute durch einen Heuballen blasen können.
Oder zumindest ähnliches vorturnen .
Grüße zurück
Biber
[/noch OTiger]
moin,
normal kommt ja auch ein Fehler, wenn eine bestimmte Datei nicht existiert, aber wenn die Zeile eingelesen wird und eine Datei lesegeschützt zum Schreiben geöffnet wird - wird diese in diesem Moment auch erstellt und ist auch vorhanden bei der ausführung der Batch-/CMDZeile.
aber als kleinen test im CMD:
wegen der einzelumleitung des kompletten Befehles ist es ja so, das zu Beispiel:
bei mir ~ 5 sekunden dauerte, aber
~ 1 min 45 sek dauerte
Zeitmessung über Batchdatei
das kann ich mir nur erklären das beim 1. mal die Datei nur 1 mal geöffnet und abschliesend geschlossen wird -> schprich ein Schreibzugriff
beim zweiten mal hingegen wird die Datei 100.000 mal geöffnet und auch genausoviel mal wieder geschlossen - abgesehne von den Lese-/Schreibzugriffen in der MFT
was allerdings die Forschleife von Jeb macht kann ich nicht erklären.
Gruß Phil
Wenn eine Umleitung mit einer Pipe (also hier dem ">"-Zeichen) verlangt wird, dann wird zuerst das Ziel als Filehandle geöffnet,
genau das wollte ich auch gerade schreibennormal kommt ja auch ein Fehler, wenn eine bestimmte Datei nicht existiert, aber wenn die Zeile eingelesen wird und eine Datei lesegeschützt zum Schreiben geöffnet wird - wird diese in diesem Moment auch erstellt und ist auch vorhanden bei der ausführung der Batch-/CMDZeile.
aber als kleinen test im CMD:
if exist "%temp%\testdatei.txt" del "%temp%test\datei.txt"
type "%temp%\testdatei.txt"
type "%temp%\testdatei.txt">"%temp%\tesdatei.txt"
type "%temp%\testdatei.txt"
wegen der einzelumleitung des kompletten Befehles ist es ja so, das zu Beispiel:
type nul>D:\testdatei.txt
(for /l %i in (1,1,100000) do @echo.)>D:\testdatei.txt
type nul>D:\testdatei.txt
for /l %i in (1,1,100000) do @echo.>>D:\testdatei.txt
Zeitmessung über Batchdatei
das kann ich mir nur erklären das beim 1. mal die Datei nur 1 mal geöffnet und abschliesend geschlossen wird -> schprich ein Schreibzugriff
beim zweiten mal hingegen wird die Datei 100.000 mal geöffnet und auch genausoviel mal wieder geschlossen - abgesehne von den Lese-/Schreibzugriffen in der MFT
was allerdings die Forschleife von Jeb macht kann ich nicht erklären.
Gruß Phil