Batch-Fold-Textdateien mit Bash-Skript

905
Frank_Zafka

Es fällt mir schwer, etwas ganz einfaches zu machen. Ich habe ca. 2000 .txt-Dateien, die aus einer einzelnen Ziffernzeile bestehen. Ich möchte die einzelne Zeile mit dem Befehl fold in eine Spalte mit vielen Zeilen falten und die Originaldatei mit dieser neuen, gefalteten Version überschreiben. Mein Versuch:

#!/bin/bash for i in *.txt ; do fold -w 1 $file > $file done 

Funktioniert nicht Hilfe? Vielen Dank.

2
Um zu vermeiden, dass temporäre Dateien direkt bearbeitet und bereinigt werden müssen, lesen Sie den Abschnitt `sponge` aus dem Paket` moreutils` unter [Bearbeiten von Dateien an Ort und Stelle] (http://backreference.org/2011/01/29) / In-Place-Bearbeitung von Dateien /), Peter.O vor 11 Jahren 0

2 Antworten auf die Frage

5
terdon

Hier gibt es zwei Probleme. Zuerst deklarieren Sie die Variable "i", verwenden jedoch "$ file", die nicht vorhanden ist. Auch wenn dies der Fall ist, lautet das zweite Problem, dass bash "von links nach rechts" liest. Das bedeutet, dass zuerst "> $ file" angezeigt wird und der Inhalt der Datei überschrieben wird. Wenn Sie also die richtigen Variablen verwenden, hätten Sie Ihre Daten verloren.

Also, ein Fehler hat dich vor dem anderen gerettet, du Glücklicher, Glückspilz :)

Versuchen Sie etwas wie:

for i in *.txt ; do fold -w 1 $i > sillytmpfile; mv sillytmpfile $i; done 
Zu meiner Verteidigung habe ich Killa-Grippe. Werde es versuchen. Nur aus Neugier. Ich habe 18 GB TXT-Dateien. Irgendwelche Wege ohne temporäre Datei? Vielen Dank. Frank_Zafka vor 11 Jahren 0
@RSoul The tmpfile is created once for every file and removed immediately, shouldn't cause you any problems. The only way to do it without a tmp file would be to redirect the folded output to another file: `for i in *.txt ; do fold -w 1 $i > $i".folded"; done`. That, however, will double the number of files and I would not recommend it. terdon vor 11 Jahren 1
Okay. Alles Teil der Lernkurve. :) Frank_Zafka vor 11 Jahren 0
Sie können es optimieren, wenn Sie den Pfad für `sillytmpfile` so wählen, dass er sich auf einer Ramdisk befindet. Unter Linux ist dies normalerweise `/ tmp`,` / run / shm`, vielleicht auch andere, überprüfen Sie mit `mount | grep tmpfs`. Thor vor 11 Jahren 0
2
Thor

sed Möglicherweise auch eine Option, behandelt das Problem der temporären Datei intern:

for i in *.txt ; do sed -i 's#.#&\n#g' $file done 
Interessant. Ich werde eines Tages zu Sed kommen. ;) Frank_Zafka vor 11 Jahren 0
Erstellt trotzdem eine tmp-Datei. Und meine * Vermutung * ist, dass es etwas länger dauern wird, da es einen regulären Ausdruck hat, der ausgewertet werden muss, und die gesamte Zeile danach durchsucht wird. terdon vor 11 Jahren 0
Yes, it is definitely slower, Try this with both `fold` and `sed`... `time printf '%sabcdef\n' |fold -w 1 >/dev/null` ... Also the **output is different** because of the way in which original newlines are handled. Peter.O vor 11 Jahren 1
@ PeterO: Um 6 mal langsamer durch meine Messungen, aber ich bekomme keinen Unterschied in der Ausgabe. Thor vor 11 Jahren 0
Maybe it is a version issue. Here are my commands and results of `wc` line counts: ... ***fold*** *(GNU coreutils) 7.4* `printf '%sabcdef\n' |fold -w 1 |wc -l # -> 11888896` ... *GNU* ***sed*** *version 4.2.1* `printf '%sabcdef\n' |sed 's#.#&\n#g' |wc -l # -> 12888896` Peter.O vor 11 Jahren 0
Ah I see, `sed` includes newlines from input in output, I missed it before because my `diff` ignores whitespace. So `printf '%sabcdef\n' | tr -d '\n' | sed 's#.#&\n#g' | wc -l # -> 11888896`. But as noted, `fold` is a better choice for the OP. Thor vor 11 Jahren 0