Wie automatisiere ich: Textdatei nur jede 10. Zeile behalten

C

CAR

Jungspund
Hallo,

ich suche nach einer Automatisierung folgender Aufgabe:

1. Textdatei öffnen
2. jede 10. Zeile behalten, alle anderen löschen
3. Textdatei speichern und schließen

Das ganze soll für mehrere Textdateien in einem Verzeichnis ausgeführt werden.

Wie könnte ich das unter MacOSX 10.5 automatisieren?
Mit Automator gehts wohl nicht. Vielleicht mit SED via Terminal? Wenn ja, welche Anweisung benötige ich dafür? Bin sehr dankbar über einen Tipp!!!

CAR
 
Zuletzt bearbeitet:
Hi,

dieser kleine Hack fuer die bash und sed sollte das tun was du willst:
Code:
for file in ./*; do
   sed -i '1,9d' "$file" && sed -i '2,$d' "$file"
done
Die For-Schleife iteriert ueber alle Dateien im aktuellen Verzeichnis, und loescht erst die ersten 9 Zeilen, und dann in der geaenderten Datei alles ab der 2. Zeile.

mfg,
bytepool
 
Code:
for file in ./*; do
   sed -i '1,9d' "$file" && sed -i '2,$d' "$file"
done

Wow! Danke. Nur wie funzt das im Detail?

Ich habe Deinen code ins Terminal kopiert, welches dann ausgibt:

> done
sed: 1: "./Desktop": invalid command code .
sed: 1: "./Documents": invalid command code .
sed: 1: "./Downloads": invalid command code .
sed: 1: "./Library": invalid command code .
sed: 1: "./Movies": invalid command code .
sed: 1: "./Music": invalid command code .
sed: 1: "./Pictures": invalid command code .
sed: 1: "./Public": invalid command code .
sed: 1: "./Sites": invalid command code .
sed: 1: "./newtext": invalid command code .

Das es nicht so gehen kann, ist mir schon klar. Nur für mich als Newbie: Wo muss sich das Verzeichnis mit den Textdateien befinden und wohin werden die Textdateien mit den gelöschten Zeilen ausgegeben?
 
Hi,
Ich habe Deinen code ins Terminal kopiert [...]
Oehm, kann es sein dass du gar keine Ahnung vom Umgang mit der Shell hast? Wenn du das jetzt einfach so in deinem Home Verzeichnis ausgefuehrt hast, hoffe ich fuer dich, dass du da entweder keine wichtigen Dateien drin hattest, oder dass der sed Befehl in der Tat ueberhaupt nicht funktioniert hat. Sonst haettest du jetzt naemlich gerade alle deine Dateien im Home Verzeichnis verstueckelt.
Ich schrieb "Die For-Schleife iteriert ueber alle Dateien im aktuellen Verzeichnis", womit ich selbstverstaendlich das aktuelle Verzeichnis der Shell (des Terminals) meinte.

Das es nicht so gehen kann, ist mir schon klar. Nur für mich als Newbie: Wo muss sich das Verzeichnis mit den Textdateien befinden und wohin werden die Textdateien mit den gelöschten Zeilen ausgegeben?
Die Option -i von sed steht fuer "in-place", d.h. alle Aenderungen die sed durchfuehrt, werden direkt in der Datei selbst gemacht, in etwa so, als wuerdest du die Aenderungen im Texteditor machen, und dann speichern.

Das Verzeichnis kannst du dementsprechend entweder direkt im Skript festlegen, oder du wechselst einfach in das entsprechende Verzeichnis.

Ich kenne mich mit Macs im speziellen nicht aus, und weiss dementsprechend auch nicht, welche Shell dort als standard Shell verwendet wird.

Zu deinem konkreten Problem muesste man also erstmal wissen, welche Shell du verwendest ('echo $SHELL' geht meistens), und welche sed Version du benutzt ('sed --version').

Jetzt muss ich leider auch erstmal weg.

mfg,
bytepool
 
Zuletzt bearbeitet:
welche Shell du verwendest ('echo $SHELL' geht meistens)

Geb ich das ein, kommt Folgendes zurück:
/bin/bash


und welche sed Version du benutzt ('sed --verison').

sed: illegal option -- -
usage: sed script [-Ealn] [-i extension] [file ...]
sed [-Ealn] [-i extension] [-e script] ... [-f script_file] ... [file ...]


soweit so gut.

Ansonsten ist durch das Ausführen Deines Scriptes nichts zerstört wurden.

....

Also, was ich auf jeden Fall schon mal hinbekomme, ist das einfache Löschen von mehreren Zeilen: geht so:

sed -e '1,3D' testdatei.txt > testdatei_neu.txt

...löscht die 1. drei Zeilen der Textdatei "testdatei.txt" Wahnsinn!!!
 
Zuletzt bearbeitet:
Code:
#!/bin/bash

#Länge der Datei bestimmen
length=`wc -l $1|{ read len nirvana; echo $len; }`;
#Dateiname
filename=$1."10thlines"

#Ausgabe alter Durchläufe löschen und Datei neu anlegen
rm $filename
touch $filename

echo "Länge: $length,Ausgabedateiname: $filename"

#Jede 10. Zeile ausgeben
i=10;
while [ $length  -gt $i ];
do 
    cat $1|head -n $i|tail -n 1 >> $filename;
    i=`expr $i + 10`;
done

Es geht auch ohne Sed :D

PS
Wenn du mehr über Shell Scripting,Sed,Grep,Perl und Geschwister wissen möchtest, schau dir mal das Linux Openbook an: http://openbook.galileocomputing.de/linux/ Die ersten sieben Kapitel sollten ganz hilfreich sein.

So Zeit für ein wenig Bewegung
 
Zuletzt bearbeitet:
Herzlich Glueckwunsch, zur ihren Top Post kann ich nur begluecken, Da nun alle Gluecklich sind koennen wir ja den Thread schliessen.

/ironie off

Kann es sein das du keine bash hast?
Code:
bash --version
oder -v sollte hier hilfreich sein.

Ansonsten waere eine deteilreicher Fehler beschreiubung hier eine Tip.
 
Sorry, wenn ich hier die Informatikprofis aufrege, aber ich bin eben kein solcher und will es dennoch schaffen. Ich will hier niemanden beleidigen und erwarte es umgekehrt ebenso.

Es tut mir also leid, dass ich in meinem letzten Beitrag so kurz war - aber das Skript funktioniert bei mir tatsächlich nicht. Ich kannte die Seite zum dem openbook schon, allerdings arbeite ich nicht auf Linux, sondern MacOSX.

Folgendes Script funktioniert für eine Datei:

sed -n '1,${p;n;n;n;n;n;n;n;n;}' datei.txt > dateineu.txt

Ich erhalte "dateineu.txt" mit den jeweils 10. Zeilen. So wollt ich es haben.

Leider habe ich mehr als hundert Dateien zu bearbeiten, was bedeutet, dass ich mit der manuellen Dateinamensvergebung nicht weiter komme.

bytepools Script verstehe ich als Schleife, in der Dateien eines Verzeichnisses bearbeitet und wieder gespeichert werden. Allerdings ist das mehr Ahnung, als Verstehen.

Ich suche also weiter danach:
Wie kann ich x txt-Dateien aus einem Verzeichnis öffnen, jeweils die 10 Zeile darin löschen und wieder als Datei ausgeben.

Vielleicht könnt mir doch noch mal Jemand auf den Weg helfen...

CARolin
 
Achso das vergaß ich zu erklären:
Du musst den Code in einer Textdatei speichern (keine Textverarbeitung verwenden !). Dann musst du ein Terminal öffnen, in den Ordner wechseln in dem du das Script gespeichert hast und es folgendermaßen aufrufen:
Code:
sh Dateiname_des_Scripts Dateiname_der_zu_bearbeitenden_Datei

Ich bau dir gleich noch eine Schleife ein die das für jede Datei im Verzeichnis erledigt

Wegen des Openbooks: Das erste Kapitel solltest du natürlich überspringen - aber ansonsten werden die allerwenigsten Programme irgendwelche Unterschiede zu den Linux-Varianten aufweisen. Führ einfach mal
Code:
bash --version;cp --version;sed --version;grep --version
aus
 
Zuletzt bearbeitet von einem Moderator:
Code:
sed --version

hier posten - da hast du vorhin beim Eingeben was falsch gemacht, wenn das hier:

sed: illegal option -- -
usage: sed script [-Ealn] [-i extension] [file ...]
sed [-Ealn] [-i extension] [-e script] ... [-f script_file] ... [file ...]

zurückkam.

Und das hier (von bytepool):

Code:
for file in ./*; do
   sed -i '1,9d' "$file" && sed -i '2,$d' "$file"
done

funktioniert wunderbar - auch unter MacOs.

Du musst nur den "." entsprechend durch deinen Verzeichnisnamen ersetzen.

Angenommen also die ganzen Dateien befinden sich in einem Verzeichnis in deinem Home-Verzeichnis namens "test" dann machst du die Konsole auf, tippelst


Code:
cd

ein (dann befindest du dich in deinem Home-Verzeichnis) und kopierst dann folgende Zeile in die Konsole:

Code:
for file in test/*; do sed -i '1,9d' "$file" && sed -i '2,$d' "$file"; done

Das "test" musst du logischerweise mit dem Verzeichnisnamen ersetzen wie er bei dir heißt.
 
Hi,

da bin ich wieder.

sed: illegal option -- -
usage: sed script [-Ealn] [-i extension] [file ...]
sed [-Ealn] [-i extension] [-e script] ... [-f script_file] ... [file ...]
Hehe, auf die sinnige Idee, dass ich mich in der Eile vertippt habe, und verison eigentlich version heissen sollte, bist du nicht gekommen, oder? ;)

Allerdings verstehe ich jetzt nach dem lesen deiner weiteren Posts schon nicht mehr, was du denn eigentlich willst. Mal soll alles bis auf die 10. Zeile geloescht werden, dann soll ploetzlich nur die 10. Zeile geloescht werden, mal soll das alles in der Datei direkt passieren, mal sollen die Aenderungen in neue Dateien geschrieben werden...
Ich verstehe noch genau Bahnhof.

Es geht auch ohne Sed :D
Stimmt, man koennte das Programm auch in Assembler, C, C++, Prolog, Java, Perl, Python, Ada, PHP oder in 20 verschiedenen Varianten als Shell Skript schreiben. Mal leichter, mal schwerer. Wo ist der Sinn der Aussage?

Herzlich Glueckwunsch, zur ihren Top Post kann ich nur begluecken, Da nun alle Gluecklich sind koennen wir ja den Thread schliessen.

/ironie off

Kann es sein das du keine bash hast?
Code:
bash --version
oder -v sollte hier hilfreich sein.

Ansonsten waere eine deteilreicher Fehler beschreiubung hier eine Tip.
Koenntest du das sinnlose trollen mal sein lassen? Das ist mir jetzt schon haeufiger aufgefallen, dass du so sinnfreie Sachen postest. Auch wenn "Noe, geht nicht" im Allgemeinen keine schoene Antwort ist, so ist deine Antwort noch schlimmer.

Ein Deutsch das schon fast unter aller Sau ist, katastrophale Interpunktion, und offensichtlich noch nicht mal die vorherigen Beitraege richtig gelesen. Die Frage nach der Shell wurde bereits gestellt _und_ beantwortet.

Ich waere dir doch sehr verbunden, wenn du in Zukunft den Kopf vorm Posten einschalten wuerdest, und den Beitrag den du schreiben willst nochmal durchliest. Wenn du dann feststellst, dass du nichts substanzielles beizutragen hast, so ist Nicht-Posten kein Verbrechen.

mfg,
bytepool
 
Zuletzt bearbeitet:
Hi,
Hehe, auf die sinnige Idee, dass ich mich in der Eile vertippt habe, und verison eigentlich version heissen sollte, bist du nicht gekommen, oder? ;)

Naja, ich habe jedes Wort sehr ernst genommen, ich nahm jedoch an, dass Dein Code korrekt ist. Ich gab also
ein und es kam die besagte Fehlermeldung heraus. Das tut sie immer noch.:(


Allerdings verstehe ich jetzt nach dem lesen deiner weiteren Posts schon nicht mehr, was du denn eigentlich willst.
Ich verstehe noch genau Bahnhof.

Also, ich habe

1. 100 Dateien in einem Verzeichnis liegen
2. Ich möchte in jeder dieser Dateien jede 10. Zeile behalten, also 10. - 20. - 30. Zeile usw., die Zeilen dazwischen löschen - also: 1. bis 9., 11. bis 19., 21. bis 29. Zeile usw.

Ich habe zwar schon eine Lösung, in dem ich die Dateien durch eine Datenbanksoftware filtere, brauche dabei aber pro Datei 20 Minuten, was bei 100 Dateien unendlich lange dauern würde...

So kam ich auf sed..

Wenn ich das hier eingebe:

for file in test/*; do sed -i '1,9d' "$file" && sed -i '2,$d' "$file"; done

kommt bei mir:

undefined label 'est/meinedatei.txt'

obwohl ich mein Verzeichnis "test" genannt habe. ??


Führ einfach mal
Code:
bash --version;cp --version;sed --version;grep --version
aus

Hab ich - Ergebnis:

GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0)
Copyright (C) 2005 Free Software Foundation, Inc.
cp: illegal option -- -
usage: cp [-R [-H | -L | -P]] [-fi | -n] [-pvX] source_file target_file
cp [-R [-H | -L | -P]] [-fi | -n] [-pvX] source_file ... target_directory
sed: illegal option -- -
usage: sed script [-Ealn] [-i extension] [file ...]
sed [-Ealn] [-i extension] [-e script] ... [-f script_file] ... [file ...]
grep (GNU grep) 2.5.1

Copyright 1988, 1992-1999, 2000, 2001 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

CARolin
 
Zuletzt bearbeitet:
Hi,

Naja, ich habe jedes Wort sehr ernst genommen, ich nahm jedoch an, dass Dein Code korrekt ist.
ich hatte mich wie gesagt in der Eile vertippt, und nahm an, dass du das dann einfach falsch abgetippt hast. Aber wenn auch --version nicht funktioniert, dann benutzt du jedenfalls eindeutig kein GNU sed. Versuch doch mal 'man sed', was dir das Handbuch deiner sed Version anzeigen sollte. Dort sollten dann auch alle moeglichen Optionen deiner sed Version aufgelistet werden. Zu verlassen mit 'q'.

Also, ich habe

1. 100 Dateien in einem Verzeichnis liegen
2. Ich möchte in jeder dieser Dateien jede 10. Zeile behalten, also 10. - 20. - 30. Zeile usw., die Zeilen dazwischen löschen - also: 1. bis 9., 11. bis 19., 21. bis 29. Zeile usw.
Dann habe ich dich eindeutig missverstanden, ich dachte du wolltest nur die 10. Zeile einer jeden Datei behalten. Das macht die Sache ein wenig komplexer.
Was ich aber immer noch nicht verstanden habe, ob du die Aenderungen direkt in den Dateien selber haben willst, oder ob neue Dateien angelegt werden sollen. Aber wenn du vorher Backups machst, was man sowieso immer machen sollte, ist das ja eigentlich auch Schnuppe. ;)

Naja, ich habe leider keine Zeit mehr, und bin die naechsten 2 Tage wahrscheinlich nicht online, aber vielleicht findet sich ja noch jemand, der einen Loesungsansatz fuer dich hat.

mfg,
bytepool
 
Code:
#!/usr/bin/perl -w

use strict;
my $fh;
my $file;
my $i;
my $text;

foreach $file (glob("*.txt")) {#fuer alle txt-Dateien im jetzigen Ordner
#Bei dir evtl "foreach $file (glob("Ordner/*.pst")) {"
#Bei "foreach $file (glob("Ordner/*")) {" ist die Dateiendung Wurscht
$text = "";
$i=1;
open(FH,"$file");
while (<FH>) {
if ($i == 10) {
$text .= $_;
$i=0;
}
$i++;
}
close FH;

open(FH,">$file");
print FH $text;
close FH;
}

Ist in perl geschrieben. Wie vorhin schon gesagt pass auf was du machst! Du kannst damit eineigen Mist machen.
 
So bei mir funktioniert es jetzt wunderbar:
Code:
#!/bin/bash
suffix=".10thline"
for file do
   if [ -n `echo \"$file\" | grep \"^$suffix\";`]  
     then
     length=`wc -l $file|{ read len nirvana; echo $len; }`;
     filename=$file.$suffix
     rm $filename
     touch $filename
     i=10;
     echo "Länge: $length,Ausgabedateiname: $filename"

     while [ $length  -gt $i ];
     do 
         cat $file|head -n $i|tail -n 1 >> $filename;
         i=`expr $i + 10`;
     done
   fi
done

Speicher den Code in einer Textdatei (bei mir heist sie nthline.sh) und führe diese dann mit folgenden Befehlen aus :

Code:
cd /Verzeichnis/in/dem/die/Textdateien/liegen/
bash /pfad/zum/skript.sh *

Bei mir sieht das z.b so aus:

Code:
jbr@kamel:~$ cd /home/jbr/trash/10thline/
jbr@kamel:~/trash/10thline$ sh nthline.sh *
rm: Entfernen von „nthline.sh.10thline“ nicht möglich: Datei oder Verzeichnis nicht gefunden
Länge: 19,Ausgabedateiname: nthline.sh.10thline
rm: Entfernen von „nthline.sh~.10thline“ nicht möglich: Datei oder Verzeichnis nicht gefunden
Länge: 19,Ausgabedateiname: nthline.sh~.10thline
rm: Entfernen von „test.10thline“ nicht möglich: Datei oder Verzeichnis nicht gefunden
Länge: 32,Ausgabedateiname: test.10thline
rm: Entfernen von „test2.10thline“ nicht möglich: Datei oder Verzeichnis nicht gefunden
Länge: 23,Ausgabedateiname: test2.10thline
jbr@kamel:~/trash/10thline$ ls
nthline.sh   nthline.sh~.10thline  test           test2
nthline.sh~  nthline.sh.10thline   test.10thline  test2.10thline
jbr@kamel:~/trash/10thline$ cat test
VORSTADT IM FÖHN
Am Abend liegt die Stätte öd und braun,
 Die Luft von gräulichem Gestank durchzogen.
 Das Donnern eines Zugs vom Brückenbogen —
 Und Spatzen flattern über Busch und Zaun.

 Geduckte Hütten, Pfade wirr verstreut,

In Gärten Durcheinander und Bewegung,
 Bisweilen schwillt Geheul aus dumpfer Regung,
 In einer Kinderschar fliegt rot ein Kleid.

 Am Kehricht pfeift verliebt ein Rattenchor.
 In Körben tragen Frauen Eingeweide,

Ein ekelhafter Zug voll Schmutz und Räude,
 Kommen sie aus der Dämmerung hervor.

 Und ein Kanal speit plötzlich feistes Blut
 Vom Schlachthaus in den stillen Fluß hinunter.
 Die Föhne färben karge Stauden bunter

Und langsam kriecht die Röte durch die Flut.

 Ein Flüstern, das in trübem Schlaf ertrinkt.
 Gebilde gaukeln auf aus Wassergräben,
 Vielleicht Erinnerung an ein früheres Leben,
 Die mit den warmen Winden steigt und sinkt.

 Aus Wolken tauchen schimmernde Alleen,
 Erfüllt von schönen Wägen, kühnen Reitern.
 Dann sieht man auch ein Schiff auf Klippen scheitern
 Und manchmal rosenfarbene Moscheen.
jbr@kamel:~/trash/10thline$ cat test.10thline
 Bisweilen schwillt Geheul aus dumpfer Regung,
 Vom Schlachthaus in den stillen Fluß hinunter.
 Aus Wolken tauchen schimmernde Alleen,

Das Skript ist als solches harmlos, aber wie immer kann ich natürlich nicht dafür garantieren das es nicht doch irgendwelche Dateien löscht, andere Schäden anrichtet oder funktioniert. Verwende es nur wenn keine der Dateien auf .10thline endet oder passe $suffix entsprechend an.
 
Zuletzt bearbeitet:

Ähnliche Themen

3 letzte Zeile löschen oder ab Zeile 55 Muster suchen und löschen

Server-Monitoring mit RRDTool

Zurück
Oben