Sie sind nicht angemeldet.

Lieber Besucher, herzlich willkommen bei: Linux Forum Linux-Web.de. Falls dies Ihr erster Besuch auf dieser Seite ist, lesen Sie sich bitte die Hilfe durch. Dort wird Ihnen die Bedienung dieser Seite näher erläutert. Darüber hinaus sollten Sie sich registrieren, um alle Funktionen dieser Seite nutzen zu können. Benutzen Sie das Registrierungsformular, um sich zu registrieren oder informieren Sie sich ausführlich über den Registrierungsvorgang. Falls Sie sich bereits zu einem früheren Zeitpunkt registriert haben, können Sie sich hier anmelden.

1

31.05.2010, 19:00

[gelöst] Listenerstellung in for - Schleife

Jetzt bin ich doch schon wieder da....
Es geht wieder um ein bash-Skript. Vorher noch eine Anmerkung : ich benutze als Infoquelle im Wesentlichen den "Advanced Bash-Scripting Guide" v5.2 von Mendel Cooper. Der ist zwar ziemlich komplett aber meiner Meinung nach ebenso schwer zu lesen. Was mich da vor allem stört ist das "Verstecken" von wichtigen Infos in unscheinbaren Nebensätzen. Ich tu mich einfach schwer, wenn ich eine bestimmte Funktion suche von der ich den Befehl nicht genau weiß.
Gibt es vielleicht was ähnliches das besser strukturiert aber weniger ausführlich ist ?

Jetzt zur eigentlichen Frage :
ich will eine for - Schleife auf einige Dateien anwenden. Die Schleife lautet

Quellcode

1
 for i in ${anfang}*.dat; do 

die Variable anfang wird vorher entsprechend definiert. Durch das * wird ja zuerst eine Liste mit den entsprechenden Dateinamen erstellt. Was ich jetzt wissen möchte : wie wird diese Liste erstellt ? Alphabethisch sortiert oder nach den Inodes der Dateien oder irgendwie "zufällig".
Im jetzigen Fall ist das * immer eine Zahl, meistens zweistellig, manchmal dreistellig, selten auch mal nur einstellig.

Ich möchte den aktuellen Wert der Variablen i weiterverarbeiten, dazu muß ich aber sicher sein, das das i auch wirklich immer mit aufsteigenden Zahlen im Platzhalter * bestückt ist. Um da falls notwendig was zu ändern reicht es eben nicht aus, einfach mal ein paar Versionen durchzutesten und zu schauen was dabei rauskommt. Ich denke, dazu muß ich die Regeln (falls es sowas gibt) für die Listenerstellung in einer for- Schleife wissen.

Jemand eine Idee ?

Danke schon einmal im Voraus !

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »delix« (31.05.2010, 19:03)


linuxerr

Prof. Dr. Schlaumeier

  • »linuxerr« ist männlich

Beiträge: 8 557

Wohnort: Mecklenburg, zur Entwicklungshilfe in Chemnitz/Sachsen ;-)

  • Nachricht senden

2

05.06.2010, 19:58

RE: Listenerstellung in for - Schleife

diese expansion nimmt ja nich for vor, sondern die bash. die sortierung sollte lexikalisch erfolgen. das bedeutet auch, das die datei dat03.txt vor der datei dat2.txt gelistet wird. wenn du sichergehen willst, dann bau eine eigene sortierfunktion.
bei der einfachen expansion der dateiliste bekommst du ausserdem ein problem, wenn es sehr viele dateien im treffer gibt, dann meldet die bash "line too long" und dein script bricht ab. besser ist es, eine while-schleife zu verwenden und die ergebnisse von ls zeilenweise mit read einzulesen.
Die Rechtschreibfehler in diesem Beitrag sind nicht urheberrechtlich geschützt.
Jeder der einen findet darf ihn behalten und in eigenen Werken weiterverwenden.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »linuxerr« (05.06.2010, 19:59)


3

06.06.2010, 02:11

Bei zu vielen Dateien darf man gar nicht über die bash glob-en, weil auch "ls -1 *.foo|while read -r bar; do ... done" würde zum Problem. Man darf dann also gar keine '*' benutzen und muss nachträglich pro Datei filtern oder find benutzen.

Zur Sortierung siehe "man ls", gleich im ersten Absatz von DESCRIPTION.

Besser als der "Advanced foobar egal" v-blah von Wichtigtuer Wichtig ist "man bash", weil da hat der das nachgelesen, worüber er schreibt.

//edit um Missverständnissen vorzubeugen
Ich beziehe mich mit der Sortierung nicht auf die for-Schleife sondern nur auf "ls -1|while read -r foo do if echo "$foo"|egrep "^${anfang}.*\\.dat\$"; then ... fi done".

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »oziris« (06.06.2010, 02:24)


4

06.06.2010, 11:32

Danke für die Antworten !
Das mit dem 03 kommt vor 2 habe ich bei den Testdurchläufen auch schon bemerkt. Das Ganze wird wirklich etwas kompliziert....
Das mit dem Sortieren werde ich jetzt einmal vorerst ad acta legen, da ich da bis jetzt noch keine umsetzbare Lösung gefunden habe. Wenn ich dann auch noch Probleme mit der Listenlänge bekommen, geht's schon mal gar nicht. Ich habe maximal 500 Listenelemente, das wird dann wohl für eine for - Schleife schon zu viel sein, aber mit der while sollte ich doch dann den Platzhalter * noch verwenden könne, oder nicht ?

Was ich demnächst ausprobieren werde : die Dateien einzel auslesen, den Dateinamen auseinandernehmen, mit einer Case Anweisung analysieren und dann mit einer Zählvariable umbennen und dann so weiterverarbeiten. Ich hoffe, ich kann das auch so umsetzen, dass ich das dann passt.

Vielen Dank also für's erste für die Tipps.
Ich befürchte, da werde ich mich noch öfter melden müssen..... . Ich habe nicht geglaubt, dass das so knifflig wird.
Also bis demnächst in diesem Theater :party:

Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von »delix« (06.06.2010, 11:45)


5

06.06.2010, 21:42

Zitat

Original von delix
Ich habe maximal 500 Listenelemente, das wird dann wohl für eine for - Schleife schon zu viel sein, aber mit der while sollte ich doch dann den Platzhalter * noch verwenden könne, oder nicht ?
Nein, das könnte die for-Schleife noch aushalten. Aber wenn es mit for nicht geht, dann kannst Du es mit "*" und while auch vergessen.

Es gibt irgendwelche maximalen Begrenzungen für alles (Siehe z.B. "xargs --show-limits"). Solbald Du ein * verwendest, wird es von der Shell in eine, mit Leerzeichen getrennte, Liste aller passenden Dateien umgewandelt aus der Gesamtanzahl der Zeichen in der Liste plus evtl. ggf. anderen Parametern, ergibt sich dann eine Größe, die ein gewisses Maß nicht überschreiten darf. Daher darf man das * bei großen Datei-Mengen nicht verwenden. Auch nicht, beim Pipen in ein while. Man muss das dann anders lösen.

Tatsächlich hält das "for i in *.wtf; do" etwas mehr aus, als das "ls -1 *.wtf|while read -r i; do" (wegen der Begrenzung der Parameterliste, denn for ist eine Kontrollstruktur und hat keine Parameterliste; ls steigt aber evtl. mit "Argument list too long" aus) dennoch kann es bei beiden zu Problemen kommen. Ganz sicher wäre aber ein "ls -1|while read -r i; do if echo "$i"|egrep '.*\.wtf'; then", dabei hätte aber die CPU mehr zu tun.

Übrigens rede ich hier nicht über Größenordnungen von 500 Dateien, sondern mehr so über 6- oder 7-stellige Zahlen als Minimum.

Ohne "*" und mit find gibt es quasi kein Limit, ohne "*" und mit ls gibt es evtl. eine OoM-Exception, mit "*" und mit for gibt es evtl. ebenfalls eine OoM-Exception und mit "*" ls und while gibt es evtl. viel früher schon einen "Argument list too long"-Fehler.

Thema bewerten