Einsteigerfrage zu Shellprogrammierung

Post Reply
Message
Author
flo2
Posts: 46
Joined: 27. May 2002 21:28

Einsteigerfrage zu Shellprogrammierung

#1 Post by flo2 »

Hallo,

ich habe folgendes Problem: Ich will ein Shellscript schreiben, das alle Dateien in einem Verzeichnis mit der Endung *.pid löscht. Das ganze soll natürlich nur erfolgend, wenn solche Dateien vorhanden sind. Ich habe folgendes versucht:

Erste Versuche natürlich mit test -e bzw. -f. Also if test -f *.pid Ist der Gebrauch von Wildcards bzw. Platzhaltern bei diesem Befehl zulässig?

Zweiter Versuch mit "if find -name *.pid -print -exec rm {} ;<!--no--> Problem: Der if Zweig (=Löschen) wird auch ausgeführt, wenn überhaupt keine pid-Dateien gefunden werden. find liefet wohl immer ein true zurück.

Gibt es sonst noch eine funktionierende Lösung?

Danke
Flo

tkortkamp
Posts: 143
Joined: 08. Apr 2001 22:56
Location: Bremen

Re: Einsteigerfrage zu Shellprogrammierung

#2 Post by tkortkamp »

Hi!

Also am einfachsten ist es doch <blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">rm -f *.pid</font><hr></pre></blockquote> zu benutzen. Die -f Option ignoriert nicht-existierende Dateien und veranlasst rm niemals irgendwas nachzufragen.

c ya,
Tobias

Flo

Re: Einsteigerfrage zu Shellprogrammierung

#3 Post by Flo »

Hallo,

ok, das stimmt natürlich. Nur bin ich nicht 100% damit zufrieden, weil das rm Kommando auch aufgrerufen wird, wenn überhaupt keine .pid Dateien vorhanden sind. Ich würde gerne unnötige Aufrufe verhindern.

Grüße
Flo

Kurt

Re: Einsteigerfrage zu Shellprogrammierung

#4 Post by Kurt »

> Ich würde gerne unnötige Aufrufe verhindern.
Warum? Das spielt doch keine Rolle, ob rm nun aufgerufen wird oder nicht. Wenn du es mit test oder find machst, werden diese Programme auch aufgerufen...

Flo

Re: Einsteigerfrage zu Shellprogrammierung

#5 Post by Flo »

Hallo,

dass ein möglicherweise unnötiger Aufruf von rm nicht gerade viel Zeit des Prozessors in Anspruch nimmt, ist mir schon klar. Aber es interessiert mich einfach, ob das Überprüfen mehrer Dateien auf ihr Vorhandensein möglich ist.

MfG
Flo

ratttengift

Re: Einsteigerfrage zu Shellprogrammierung

#6 Post by ratttengift »

hallo,
wie kurt bereits sagte, ist die "rm -f"-variante die effizienteste. wenn es dir aber um den lerneffekt geht, könntest du zb folgendes machen.
<blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">
for DATEI in *.pid; do
echo $DATEI wird gelöscht
rm $DATEI
done
</font><hr></pre></blockquote>
wie gesagt, das ist unnötig umständlich, aber vom lerneffekt her vielleicht brauchbar.

> Zweiter Versuch mit "if find -name *.pid -print -exec rm {} ;
> Problem: Der if Zweig (=Löschen) wird auch ausgeführt, wenn überhaupt keine pid-Dateien gefunden werden.

das ist auch keine richtige if-struktur. so gehts einfacher: rm $(ls *.pid)
in diesem fall werden nur die files behelligt, die wirklich existieren (wie bei rm -f natürlich auch <img src="http://www.pl-forum.de/UltraBoard/Images/Happy.gif" border="0" align="middle">)
rm wird also nur auf die files angewendet, die vom ls-command geliefert werden.

Jochen

Re: Einsteigerfrage zu Shellprogrammierung

#7 Post by Jochen »

@rattengift:

Deine for-Schleife wird immer mind. einmal durchlaufen. Weshalb? Die Filename-Substitution der Shell greift nur, wenn es auch tatsächlich Dateien gibt, auf die das Muster passt. Existieren keine Treffer, wird die Zeichenfolge (hier "*.pid") unverändert stehen gelassen. Die Liste der Elemente für die for-Schleife ist also entweder die Liste der Dateien, die auf .pid enden, oder aber die Zeichenfolge "*.pid".
Und wenn man ein "rm $(ls *.pid) verwendet und es sind keine solchen Dateien vorhanden, erhält man direkt 2 Fehlermeldungen: 1. Von ls, da er Daten zu einer Datei "*.pid" nicht anzeigen kann, und dann von rm, weil ihm die Argumente fehlen (die Meldung von ls landete als Fehlermeldung natürlich auf stderr und wird daher auch nicht durch $() als Argument zu rm eingesetzt).

@Flo:

"rm -f *.pid" ist die "korrekte" Version, sprich die einfachst mögliche und schnellstverstandene. Performance ist bei Shell-Skripten meist nicht erste Priorität. Sollte tatsächlich ein Problem in der Laufzeit des Skriptes bestehen, wird es sicher nicht in dem Aufruf eines einzigen externen Programmes bestehen. Meist wird dann eher in handgeschnitzten Schleifen mehrere externe Programme über viele Dateien gehetzt - dort sollte man ansetzen.

Um nun aber eine korrekte Lösung anzubieten: <blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">if [ -z "$(ls *.pid 2>/dev/null)" ] ; then
echo "Keine PID-Dateien vorhanden"
else
echo "Löschen PID-Dateien"
rm *.pid
fi</font><hr></pre></blockquote>
Wenn der Rückgabewert des test-Kommandos (hier als [ geschrieben) gleich 0 ist, wird der then-Zweig durchgeführt, sonst der else-Zeig. Das test-Kommando prüft, ob die Zeichenkette, die ls zurückliefert, die Länge 0 hat (-z, zero length). Damit die Shell eine leere Ausgabe nicht wegoptimiert, müssen Anführungszeichen um die Kommandosunstition $() gesetzt werden.

Wie Du siehst, ein Sturm im Wasserglas. Bleib besser bei "rm -f" <img src="http://www.pl-forum.de/UltraBoard/Images/Happy.gif" border="0" align="middle">.

Jochen

Flo

Re: Einsteigerfrage zu Shellprogrammierung

#8 Post by Flo »

Ein Dank geht an alle! Ich werde mich wohl doch für rm -f Methode entscheiden. <img src="http://www.pl-forum.de/UltraBoard/Images/Happy.gif" border="0" align="middle">

MfG
Flo

LBS

Re: Einsteigerfrage zu Shellprogrammierung

#9 Post by LBS »

@Jochen
wieso schreibst Du bei der Kommandosubstitution $() hat das irgendwelche vorteile gegenüber den ` Backticks?

cu

____________________________
Linux Based System <img src="http://www.pl-forum.de/UltraBoard/Images/Wilk.gif" border="0" align="middle">

Jochen

Re: Einsteigerfrage zu Shellprogrammierung

#10 Post by Jochen »

@LBS:

Tja - es gibt Vor- und Nachteile. Im Prinzip sind die beiden Schreibweisen gleichwertig.


<li>Vorteile

$() ist schachtelbar; Backticks nicht.

Dis Syntax passt logisch gut in die Shell-Syntax: Werden Kommandos in runden Klammern gruppiert, werden diese in einer eigenen Shell ausgeführt. Stellt man $ vor einen Variablennamen, wird dort der Inhalt der Variable eingefügt. Stellt man also $ vor (), wird dort die Ausgabe der Kommandos in den runden Klammern eingefügt.

Die Backticks sind fallen weniger auf und sind daher m.E. weniger gut lesbar.


<li>Nachteile

$() ist nicht rückwärtskompatibel zur Bourne-Shell, welche nur die Backticks kennt. (Allerdings verstehen sowohl bash als auch ksh/pdksh "$()").

Man muss ein Zeichen mehr tippen. <img src="http://www.pl-forum.de/UltraBoard/Images/Happy.gif" border="0" align="middle">

Wenn man tatsächlich schachtelt, wird es schnell unübersichtlich.


Jochen

Post Reply