PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Bash: etwas anders Dateinamen vergleichen?



meinereinerseiner
08-10-2008, 14:20
Hi,

ich würde gerne in einer for schleife Dateien verarbeiten, allerdings bei einigen gezielt etwas anderes tun.
Denke mal das es ein änliches Problem wie in: http://www.mrunix.de/forums/showthread.php?t=61090 ist.

mein Ansatz:


#!/bin/sh
#

for logfile in `ls /tmp/motest`
do

for MOF in `cat /tmp/motest.exclude`
do

if [ "$MOF" = "$logfile" ]; then
echo "$logfile mo-file"
else
echo "$logfile kein mo-file"
fi

done

done


liefert mir als Ausgabe:
tom@devil-ng:~> watchdog-test.sh
1 mo-file
1 kein mo-file
2 kein mo-file
2 kein mo-file
3 kein mo-file
3 mo-file
4 kein mo-file
4 kein mo-file

ich brauche aber:
tom@devil-ng:~> watchdog-test.sh
1 mo-file
2 kein mo-file
3 mo-file
4 kein mo-file

in /tmp/motest gibts 4 files 1,2,3,4 und in /tmp/motest.exclude steht untereinander 1 und 3.

Ich finde beim besten willen meinen fehler nicht, vor allem warum er das alles 2x macht und bei 1 und 3 zwei verschiedene ergebnisse hat.

tom

msi
08-10-2008, 14:37
na deine for schleife geht alle dateien mit allen checkdateien durch.

in /tmp/motest gibts 4 files 1,2,3,4 und in /tmp/motest.exclude steht untereinander 1 und 3.

also er geht folgende varianten durch:

/tmp/motest/1 vergleichen mit /tmp/motest.exclude/1
/tmp/motest/1 vergleichen mit /tmp/motest.exclude/3
/tmp/motest/2 vergleichen mit /tmp/motest.exclude/1
/tmp/motest/2 vergleichen mit /tmp/motest.exclude/3
/tmp/motest/3 vergleichen mit /tmp/motest.exclude/1
/tmp/motest/3 vergleichen mit /tmp/motest.exclude/3
/tmp/motest/4 vergleichen mit /tmp/motest.exclude/1
/tmp/motest/4 vergleichen mit /tmp/motest.exclude/3

was du machen musst ist dir eine variable halten und sobald
die datei in exclude vorkommt diese auf false setzen (davor) true

am einfachsten gehts so, wenn du die einzelnen dateinamen in dem verzeichnis /tmp/motest.exclude anlegst:



for i in `ls /tmp/motest`; do if [ -f /tmp/motest.exclude/$i ]; then echo kein $i; else echo $i; fi; done


oder wenn dus in der datei stehen hast (so wies bei dir ist)


for i in `ls /tmp/motest`; do cat /tmp/motest.exclude | grep "$i" >/dev/null ; if [ "$?" -eq 0 ]; then echo kein $i; else echo $i; fi done


also für dich die letzte variante.

Anmerkung: Beide sind SEHR inperformant, wenns performant haben willst solltest du anderst vorgehen, das ist nur quick&easy

meinereinerseiner
08-10-2008, 16:38
super, funnzt!

danke!

jan61
12-10-2008, 14:21
Moin,


...


for i in `ls /tmp/motest`; do cat /tmp/motest.exclude | grep "$i" >/dev/null ; if [ "$?" -eq 0 ]; then echo kein $i; else echo $i; fi done
...

hm, wieder mal ein "useless use of cat award" ;-)

Wieso nicht gleich die Möglichkeiten des grep nutzen?


for i in `ls /tmp/motest`; do
if grep -q "^$i$" /tmp/motest.exclude; then
echo "$i in exclude"
else
echo "$i nicht in exclude"
fi
done
Jan

msi
12-10-2008, 16:03
weils lang nicht so spektakulär aussieht ohne ne pipe :)

jan61
13-10-2008, 21:28
Moin,

naja, dafür sehen die time myscript.sh Ausgaben umso spektakulärer aus ;-)

Jan

msi
13-10-2008, 23:36
bei der menge an daten die er so verarbeitet merkt er da keinen unterschied,
wenn mans performant haben will muss man eh anderst vorgehen und auszuschließenden daten indizieren. die pipe is zwar ineffizient, weils halt alles über kernelspace läuft aber das ist in diesem szenario absolut egal.

ob du jetzt ne ausführzeit von 0,05 oder 0,045 sekunden hast merkst du gar nicht :) wenn du die zeit nicht misst :D

jan61
14-10-2008, 19:02
Moin,

naja, ich hatte eigentlich vermutet, dass es sich dabei um Beispieldaten handelt, die u. U. im richtigen Leben etwas umfänglicher ausfallen könnten. Und die Pipe-Konstruktion schlug mir vor allem deshalb auf den Magen, weil bei jedem Schleifendurchlauf dadurch eine Subshell und ein zusätzlicher Prozess entstehen, das summiert sich schnell. Innerhalb von Schleifen sollte man IMHO immer sehr sparsam mit sowas umgehen.

Ich habe mal ein Wettrennen veranstaltet:

jan@jack:~/tmp> time ./motest1.sh # mit Pipe
kein 1
2
kein 3
4
5

real 0m0.035s
user 0m0.008s
sys 0m0.024s
jan@jack:~/tmp> time ./motest2.sh # mit grep -q
kein 1
2
kein 3
4
5

real 0m0.016s
user 0m0.005s
sys 0m0.010s
Das ist eine Einsparung von ca. 50% und wird bei größeren Datenmengen natürlich entspr. deutlicher fühlbar.

Jan

EDIT: Noch was - die Einsparung kann bei großer exclude-Datei noch drastischer ausfallen, der grep -q hat nämlich die angenehme Eigenschaft, beim ersten Treffer aufzuhören.

msi
14-10-2008, 21:56
Moin,

naja, ich hatte eigentlich vermutet, dass es sich dabei um Beispieldaten handelt, die u. U. im richtigen Leben etwas umfänglicher ausfallen könnten. Und die Pipe-Konstruktion schlug mir vor allem deshalb auf den Magen, weil bei jedem Schleifendurchlauf dadurch eine Subshell und ein zusätzlicher Prozess entstehen, das summiert sich schnell. Innerhalb von Schleifen sollte man IMHO immer sehr sparsam mit sowas umgehen.

Ich habe mal ein Wettrennen veranstaltet:

jan@jack:~/tmp> time ./motest1.sh # mit Pipe
kein 1
2
kein 3
4
5

real 0m0.035s
user 0m0.008s
sys 0m0.024s
jan@jack:~/tmp> time ./motest2.sh # mit grep -q
kein 1
2
kein 3
4
5

real 0m0.016s
user 0m0.005s
sys 0m0.010s
Das ist eine Einsparung von ca. 50% und wird bei größeren Datenmengen natürlich entspr. deutlicher fühlbar.

Jan

EDIT: Noch was - die Einsparung kann bei großer exclude-Datei noch drastischer ausfallen, der grep -q hat nämlich die angenehme Eigenschaft, beim ersten Treffer aufzuhören.


wenns um performance geht ist das eh ne sehr schlechte lösung.
wenn die exclude datei groß ist dann ist es irsinnige verschwendung
von cpu zeit da alle felder durchzugehen und immer zu vergleichen.

wenn du schon so auf performance gehen willst musst du die daten
richtig indizieren zB über nen balanzierten suchbaum oder ne hashmap.

bei der grep -q variante bist bei ner laufzeitkomplexität von O(n) für jeden durchgang
bei nem suchbaum O(ld n)

jan61
16-10-2008, 20:23
Moin,


wenns um performance geht ist das eh ne sehr schlechte lösung...

das ist schon klar, aber mit Bäumen / Hashes verlässt man fast zwangsläufig den Bereich der "normalen" Shellprogrammierung. Dann wird mindestens sowas wie awk gebraucht.

Trotzdem sollte man IMHO auch bei solch kleinen Scripts darauf achten, nicht unnötig Ressourcen zu ziehen. Wenn man sich von Anfang an darüber Gedanken macht, dann gewöhnt man sich halt dran (und meist werden die Scripts dann auch besser lesbar).

Jan