Für Exit-Bash-Schleife. BASH: Beschreibung von for-, while-, until-Schleifen und Anwendungsbeispiele

Und jetzt ist das fünfte Thema des Zyklus an der Reihe. Darin werde ich weiter auf die Kontrollstrukturen der Bash-Shell eingehen. Der vorherige Beitrag behandelte bedingte Anweisungen. Jetzt ist es an der Zeit für solche integralen Sprachstrukturen wie Schleifenanweisungen. Schleifen sind wie Bedingungen Werkzeuge, die die Kontrolle über die Reihenfolge bieten, in der Befehle ausgeführt werden.
Bash unterstützt for-, while-, until- und select-Schleifen. Lassen Sie uns nun einen genaueren Blick auf jeden von ihnen werfen.

for-Schleife-Anweisung

Die allgemeine Syntax der for-Anweisung lautet:

für variabel
Tun
Befehlsliste
Erledigt

Die for-Schleife in der Bash unterscheidet sich deutlich von der for-Schleife in Programmiersprachen wie C oder PHP. Wenn Sie also ein C-Programmierer sind, müssen Sie sich an diese Unterschiede gewöhnen, damit Sie nicht verwirrt werden.
Als Ergebnis der Schablonensubstitution wird eine Liste von Wörtern erhalten. Bei jeder Iteration nimmt die Variable jeden nachfolgenden Wert dieser Liste an, und die Befehle zwischen do und done werden ausgeführt. Die Iterationen stoppen, wenn die Wörter in der Liste erschöpft sind.
$ für Tag in Mo Di Mi Do Fr do echo „Today $day“ done
Die reservierten Wörter der for-Anweisung können auch in einer Zeile geschrieben werden, wie es im vorherigen Beitrag für die if-Anweisung der Fall war. Geben Sie dazu ";" ein. Lassen Sie uns das vorherige Beispiel unter Berücksichtigung dieser Funktion umschreiben:
$ für Tag in Mo Di Mi Do Fr; do echo "Heute ist $day"; Erledigt
Das Fehlen eines Konstrukts ist gleichbedeutend mit dem Einschreiben [E-Mail geschützt]Über Parameter [E-Mail geschützt] sagte ein.

While-Schleife-Anweisung

Die allgemeine Syntax der while-Anweisung lautet:

während Liste1
Tun
Liste2
Erledigt

Liste1 wird zuerst ausgeführt. Wenn es erfolgreich ist, d. h. Code null zurückgibt, geht die Steuerung zu list2 über. Die Iterationen werden fortgesetzt, bis das Ergebnis der Ausführung von list1 ungleich Null wird. Zum Beispiel:
i=10 while [ $i -gt 0 ]; do echo $i i=$(($i-1)) fertig; Echo "Ende"

until-Schleife-Anweisung

Die allgemeine Syntax der until-Anweisung lautet:

bis Liste1
Tun
Liste2
Erledigt

Liste1 wird zuerst ausgeführt. Wenn dies fehlschlägt, d. h. bei einem Rückgabecode ungleich Null, wird die Steuerung an list2 übergeben. Die Iterationen werden fortgesetzt, bis das Ergebnis der Ausführung von Liste1 Null wird. Zum Beispiel:
i=10 bis [ $i -lt 0 ]; do echo $i i=$(($i-1)) fertig; Echo "Ende"

Select-Schleife-Anweisung

Die allgemeine Syntax der select-Anweisung lautet:

Variable auswählen
Tun
Liste
Erledigt

Als Ergebnis der Schablonensubstitution wird eine Liste von Wörtern erhalten. Der Bediener fügt diesen Wörtern Seriennummern hinzu und gibt den gesamten Satz an den Standardfehlerstrom aus. Das Fehlen eines Konstrukts ist gleichbedeutend mit dem Einschreiben [E-Mail geschützt] Danach wird eine Eingabeaufforderung angezeigt und eine Zeile aus dem Standardeingabestrom gelesen. Wenn die Zeichenfolge eine Zahl enthält, die einem beliebigen Wort aus der Liste entspricht, erhält die Variable diese Zahl als Wert. Wenn kein passendes Wort gefunden wurde, wird der Wert der Variablen zu einem leeren String. Danach wird die Befehlsliste ausgeführt, und die Iteration wird fortgesetzt, bis das Dateiendezeichen in der Eingabezeile gefunden wird oder bis break oder return in der Befehlsliste angetroffen wird.
Die Break- und Return-Befehle werden verwendet, um den Fortschritt der Schleife zu steuern. Der Befehl break unterbricht die Ausführung der Schleife, während return einen Ergebniscode (null oder ungleich Null) zurückgibt.
Die select-Anweisung ist nützlich, um nummerierte Menüs zu erstellen. Beispielsweise befinden sich im Verzeichnis ~/temp 3 Dateien: proto.txt, file.txt und readme. Ein Beispiel für ein Skriptfragment, mit dem Sie alle schnell anzeigen können.
echo "Datei zum Ansehen auswählen:" Datei in ~/temp/* auswählen Beenden; tun, wenn [ -f $Datei ]; dann cat $file; sonst brechen; fi fertig
Wenn Sie dieses Skript ausführen, sehen wir auf dem Bildschirm:
Wählen Sie eine anzuzeigende Datei aus:
1) /home/istergul/temp/file.txt
2) /home/istergul/temp/proto.txt
3) /home/istergul/temp/readme
4) Beenden

Im nächsten Thema werden bedingte Parameterersetzungen behandelt. Ich freue mich auf Ihre Kommentare.

In diesem Vortrag lernen wir weiter kennen bash. Ich möchte Sie daran erinnern, dass wir diese Elemente berücksichtigen bash um uns zu helfen, Skripte zu verstehen Betriebssystem. Solche Elemente sind sicherlich Zyklen und Funktionen. Wenn jemand Programmieren studiert hat, wird es keine Schwierigkeiten geben, diese Probleme zu verstehen.

für Schleife

Zyklus für v bash hat zwei Arten. Betrachten Sie zunächst die klassische Version für. Die Gesamtansicht ist wie folgt:

Zwischen Elementen für Und In es wird eine Variable gesetzt, die wiederum einen Wert aus einer dazwischen gegebenen Folge von Werten annimmt In Und Tun. Zwischen Tun Und Erledigt Es gibt Befehle, die jedes Mal ausgeführt werden, wenn die Variable ihren Wert ändert. Die Schleife stoppt, wenn die Variable den letzten Wert in der Sequenz annimmt. Die Werte in der Sequenz werden durch ein Leerzeichen getrennt.

Und hier ein praktisches Beispiel:

Die Reihenfolge der Werte kann auf unterschiedliche Weise angegeben werden. Explizit - wie im obigen Beispiel, oder mit Hilfe anderer Variablen, oder mit Hilfe spezieller Befehle. Schauen wir uns einige Beispiele an. Da die Werte durch ein Leerzeichen getrennt sind, kann jede Variable, die einen String mit Leerzeichen enthält, als solcher Wert verwendet werden:

Das Ergebnis ist dasselbe wie im ersten Beispiel.

Wenn Sie eine Zahlenfolge angeben müssen, können Sie den Befehl verwenden seq und Substitutionsmechanismus. Team seq gibt eine Folge von numerischen Werten auf den Bildschirm zurück. Die Syntax ist einfach und wird aus dem folgenden Beispiel deutlich:

Ergebnis:

Kommen wir zurück zur zweiten Art. für. Oft findet man in Skripten die sogenannte C-ähnliche Option für, das für nummernbasierte Schleifen verwendet wird. Schauen wir uns ein Beispiel an:

Die Schleife wird ausgeführt, während die im Ausdruck geprüfte Bedingung wahr ist. Sobald der Ausdruck false zurückgibt, wird die Schleife beendet.

Praxisbeispiel:

#!/bin/bash
i=1
während [ $i -lt 7 ]
Tun
Echo $i
sei i=i+1
Erledigt

In unserem Beispiel prüfen wir, ob die Variable ich kleiner als (-lt), die Zahl 7 und wenn ja, dann wird der Wert der Variablen angezeigt. Ausdruck sei i=i+1, erhöht die Variable um eins, prüft erneut und so weiter. let teilt dem Interpreter mit, dass die Argumente als numerische Werte behandelt werden sollen. Diese Zeile könnte geschrieben werden als lass i++(c-ähnliche Variante). Wenn die Zahl um mehr als eins erhöht wird, kann sie geschrieben werden als: sei i+=2- in diesem Fall ich wird in Zweierschritten erhöht. Eine andere Möglichkeit, eine Variable zu erhöhen, ist die Verwendung des eingebauten Taschenrechners (funktioniert nur mit ganzen Zahlen). Der Rechner kann über doppelte Klammern aufgerufen werden: i=$(($i+1)) oder durch Quadrat: i=$[$i+1] Sie können den Taschenrechner auch in der Befehlszeile verwenden:

Bei Schleifen müssen Sie aufpassen, dass Sie nicht die Option einer Endlosschleife erhalten. Übrigens zum Debuggen bash Skripte können Sie die erste Zeile in ändern #!/bin/bash -x oder führen Sie das Skript mit dem Befehl aus bash-x:

[E-Mail geschützt]:~/linux$ bash -x ./testfor.sh
+ i=1
+ ‘[‘ 1 -gt 5 ‘]’
+ Echo i=1
i=1
+ sei i=i+1
+ ‘[‘ 2 -gt 5 ‘]’
+ Echo i=2
i=2
+ sei i=i+1
+ ‘[‘ 3 -gt 5 ‘]’
+ Echo i=3
i=3
+ sei i=i+1
+ ‘[‘ 4 -gt 5 ‘]’
+ Echo i=4
i=4
+ sei i=i+1
+ ‘[‘ 5 -gt 5 ‘]’
+ Echo i=5
i=5
+ sei i=i+1
+ ‘[‘ 6 -gt 5 ‘]’

Üben Sie unbedingt das Schreiben kleiner Skripte, um Ihr Verständnis für die Funktionsweise von Schleifen zu festigen bash.

Funktionen in bash

Funktionen gelten in bash sehr weit. Funktionen werden auf zwei Arten beschrieben: mit einem Schlüsselwort Funktion, und ohne.

Erster Weg:

Funktion Funktionsname
{
Funktionskörper
}

Zweiter Weg:

Funktionsname()
{
Funktionskörper
}

Die Funktion wird überall im Skript namentlich aufgerufen, aber erst nach der Beschreibung der Funktion selbst. Funktionen können auch Parameter übergeben werden, die mit einem Leerzeichen nach dem Aufruf (Name) der Funktion angegeben werden. Betrachten Sie ein Beispielskript bash:

#!/bin/bash
Funktionsprimer
{
if [ $# -ne 0 ]
Dann
lokal a=1
echo "Anzahl der übergebenen Parameter - $#"
denn ich bin dabei [E-Mail geschützt]
Tun
echo "$ a-ter Parameter— $i"
lass a++
Erledigt
0 zurückgeben
anders
echo "Keine Parameter übergeben"
Rückkehr 1
fi
}
echo "Aufruf einer Funktion mit Parametern:"
Grundierung a b c
Echo $?
echo "Aufruf einer Funktion ohne Parameter:"
Grundierung
Echo $?

IN dieses Beispiel eine Funktion namens gegeben Grundierung. Aufruf einer Funktion mit Parametern: Grundierung a b c und ohne Parameter: Grundierung. Im Hauptteil der Funktion sollten Ihnen alle Konstrukte mit Ausnahme von bekannt sein $# , $i Und [E-Mail geschützt] .$# - gibt die Anzahl der an die Funktion übergebenen Parameter zurück. In unserem Beispiel ist dies die Nummer 3 .[E-Mail geschützt] gibt alle Parameter in einer Zeile zurück. Im Beispiel wäre dies a b c. Und durch $1 , $2 , $3 usw. Sie können auf jeden Parameter einzeln zugreifen. $? - enthält den Ausführungscode des letzten Befehls. In unserem Beispiel der Funktionsausführungscode.

Die Funktion kann auch zurückkehren numerischer Wert per Schlüsselwort zurückkehren. In der Regel geben sie 0 zurück, wenn die Funktion ohne Fehler abgeschlossen wurde, oder einen Wert ungleich Null, wenn etwas schief gelaufen ist. Im Beispiel wird bei einem Funktionsaufruf mit Parametern der Wert 0 zurückgegeben, und wenn die Funktion ohne Parameter aufgerufen wurde, wird der Code 1 zurückgegeben.

Alles beim Übergeben von Parametern an eine Funktion funktioniert genau gleich für ein Skript. Sie können auch Parameter an ein Skript übergeben und sie auf die gleiche Weise mit bearbeiten $#, [E-Mail geschützt], $N. Aus derselben Kategorie und Option - $0 - der den Namen des Befehls zurückgibt, der das Skript gestartet hat. Wenn das Skript auf Befehl ausgeführt wurde ./script.sh, dann Echo $0 wird einen Wert zurückgeben ./script.sh, und wenn auf Befehl /home/igor/linux/script.sh, dann wird der Wert zurückgegeben /home/igor/linux/script.sh.

Eine der Grundregeln der Systemadministration kann wie folgt ausgedrückt werden: Wenn Sie oft dasselbe tun müssen, schreiben Sie ein Skript und lassen Sie es die Arbeit für Sie erledigen. Wenn Sie eine Aktion innerhalb des Skripts mehrmals ausführen müssen, sollten Sie verwenden Fahrräder. IN GNU-Bash Sie können Schleifen mit Konstrukten erstellen für, während Und bis.

Wenn Sie sich jemals für das Programmieren interessiert haben, sind Sie wahrscheinlich bereits mit diesen Konstrukten vertraut. Wenn Sie wie ich studieren bash Wenn Sie keine Programmiererfahrung hinter sich haben, ist die Verwendung von Schleifen möglicherweise nicht offensichtlich genug, um sie zu verstehen. Beginnen wir damit, die Unterschiede zwischen zu identifizieren verschiedene Arten Zyklen, und fahren Sie dann mit den Beispielen fort.

Zyklus für ist darauf ausgelegt, Aktionen zu wiederholen, bis sie alle abgeschlossen sind. Stellen Sie sich zum Beispiel vor, Sie haben ein Verzeichnis mit Bildern und müssen diese von einem Format in ein anderes konvertieren. Sie können eine Schleife verwenden für zusammen mit dem Programm Konvertieren aus dem Paket ImageMagick(oder ein anderes Programm), um beispielsweise Bilder vom JPEG-Format in das PNG-Format zu konvertieren. Oder Sie müssen beispielsweise viele Sounddateien konvertieren MP3 v OGG-Vorbis.

Zyklus während verwendet, um Aktionen zu wiederholen Tschüss durchgeführt (ist WAHR) einige Bedingung. Zyklus bis funktioniert etwas anders: es führt eine Aktion aus bis bis die Bedingung erfüllt ist. So kannst du beispielsweise kontern und eine Aktion ausführen bis bis sein Wert 10 erreicht. Sehen wir uns das anhand von Beispielen genauer an.

Beginnen wir mit einer Schleife für. Sein Format ist:

Für i in $(Befehl); befehle $i; Erledigt

Wenn Sie eine Schleife verwenden für in einem Skript ist es besser, es so zu formatieren:

#!/bin/bash für i in $(Befehl); do command $i fertig

Also zum Beispiel, wenn Sie tun müssen Sicherungen alle HTML-Dateien im Verzeichnis, können Sie den folgenden Befehl verwenden:

Für i in $(ls *html); mache cp $i $i.bak; Erledigt

Dadurch wird eine lokale Variable erstellt $i, wird der Befehl ausgeführt ls*html, deren Ergebnisse die Daten sind, die den Wert der Variablen initialisieren $i bei jedem Durchlauf der Schleife (in unserem Beispiel ist dies die Liste der vom Befehl zurückgegebenen Dateien ls, eine für jede Iteration). Als nächstes wird der Befehl ausgeführt vgl, an die unter den Parametern eine Variable übergeben wird $i.

Jemand könnte fragen, ob es obligatorisch ist, den Buchstaben zu verwenden "ich" als Variablenname? Nein. Sie können alle gültigen verwenden bash Variablennamen. Natürlich ist es besser, in Skripten aussagekräftigere Variablennamen zu verwenden, wie z $eingabe oder $html.

Ich habe ein sehr kurzes und einfaches Beispiel für die Verwendung einer Schleife gegeben für. Anstelle eines Befehls, der in einem Block ausgeführt wird Tun,verwenden Echo um die übergebenen Parameter zu sehen. Dies ist eine sehr nützliche Praxis in der Phase des Testens von Skripten sowie gute Möglichkeit helfen Ihnen, Ihre Arbeit genauer zu verstehen für.

während und bis

Betrachten Sie nun die Konstruktionen während Und bis. Außerdem werden wir Bash-Bedingungen verwenden. In unserem Beispiel verwenden wir sie, um beispielsweise festzustellen, ob der Wert einer Variablen größer oder kleiner als die Zahl X ist; ob die Datei existiert und ob es sich um ein Verzeichnis handelt. Sie können auch Bedingungen verwenden, um beispielsweise zu bestimmen, ob eine Datei lesbar ist oder ein GID-Bit in ihren Berechtigungen hat.

Lassen Sie uns versuchen, etwas Einfaches zu tun, z. B. einige leere Dateien zu erstellen. Im Leben wird Ihnen das wahrscheinlich nicht nützlich sein, aber als Beispiel ist es genau das Richtige.

#!/bin/bash i=0 while [ $i -lt 22 ] berühren Sie $i i=$[$i+1] fertig

Dieses Skript erstellt 22 Dateien mit Namen von 0 bis 21. Die Schleife läuft bis Tschüss variabler Wert $i weniger ( -lt) 22.

Lassen Sie uns nun die generierten Dateien mit einer Schleife loswerden bis:

#!/bin/bash i=0 bis [ $i -eq 22 ] do rm $i i=$[$i+1] fertig

Hier haben wir ausgetauscht während An bis, und im bedingten Ausdruck, den wir ersetzt haben "weniger" (-lt) An "gleich" (-Gl). Daher funktioniert unser Skript so lange wie der Wert $i wird nicht 22 erreichen. Und statt berühren wir verwendeten rm Dateien zu löschen, anstatt sie zu erstellen. Einfach, oder?

Schleifen sind eine äußerst praktische Sache beim Schreiben von Programmen oder Skripten, oder besser gesagt eine notwendige. Sie ermöglichen es uns, einen Teil des Codes eine bestimmte Anzahl von Malen auszuführen. Natürlich hat bash mehrere Arten von Schleifen. Wir werden Zyklen beschreiben für in, für, während, bis. Obwohl for in und for als unterschiedliche Syntaxen für dieselbe Anweisung betrachtet werden, unterscheiden sie sich meiner Meinung nach mehr voneinander als while from until.

Schleife mit Zähler für in:

Zyklus für in es ist eine Schleife mit einem Zähler. Der im Rumpf der Schleife befindliche Codeblock wird so oft wiederholt, wie es Werte in der Liste des for in-Operators gibt, wobei bei jeder Wiederholung die Zählervariable (hier heißt sie var, aber man kann es natürlich auch nennen Sie es wie Sie wollen) hat den Wert des nächsten Elements der Liste.
Wenn das Schlüsselwort do in derselben Zeile wie das Wort for steht, müssen Sie nach der Liste der Argumente (before do) ein Semikolon einfügen.
Jedes der Elemente<список>kann mehrere Argumente enthalten. Dies ist beim Bearbeiten von Parametergruppen hilfreich. In diesem Fall, um das Parsen jedes der Argumente in zu erzwingen<списке>, müssen Sie die set-Anweisung verwenden
Sie können eine Variable als Liste in einer for-Schleife verwenden.
IN<списке>für Schleifen können Dateinamen verwendet werden, die wiederum Platzhalterzeichen enthalten können. Dies kann sehr nützlich sein, wenn Sie mit einer großen Anzahl von Dateien arbeiten.
Wenn<список>nicht in der for-Schleife angegeben ist, wird die Variable so verwendet, wie sie ist [E-Mail geschützt]- Liste der Befehlszeilenargumente.
Beim Erstellen einer Liste von Argumenten kann die Befehlsersetzung in der for-Schleife verwendet werden.
Die Ausgabe der Schleife kann von stdout in eine Datei oder woanders umgeleitet werden (Sie können mehr darüber erfahren, indem Sie I / O-Umleitung analysieren).

Syntax:
für var ein<список>
Tun
<выполняемые команды>
Erledigt

Beispiel:
für Namen in name1 name2 name3 name4
Tun
echo $names
Erledigt

Loop-Anweisung für hat eine andere Schreibweise - sehr ähnlich der Syntax des for-Operators in der Sprache C. In diesem Fall werden beim Initialisieren der Zähler die Anfangswerte von Variablen oder einer Variablen gesetzt und nach jedem Durchlauf der Schleife wird die Bedingung geprüft, wenn die Prüfung wahr zurückgibt, dann beginnt der nächste Durchlauf der Schleife. Im Block<приращение счётчиков>der Wert unserer Variablen Zähler muss sich unbedingt ändern (nicht unbedingt nach oben), damit wir beim Prüfen der Bedingung früher oder später den Wert von Lügen bekommen, sonst wird die Schleife nie enden. Eine sehr bequeme und vor allem vertraute Option, wenn eine Operation eine bestimmte Anzahl von Malen wiederholt werden muss.

Mit ähnlicher Syntax:
für ((<инициализация счётчиков>; <проверка условия>; <приращение счётчиков>))
Tun
<выполняемые команды>
Erledigt

Beispiel:
für ((var=1; var<= LIMIT ; var++))
Tun
echo $var
Erledigt

while-Schleife:

Dies ist eine ziemlich einfache Konstruktion, die den Zustand hinter dem Bediener prüft während und wenn diese Bedingung wahr ist, führt es den Befehlsblock aus, der zwischen den Wörtern do und done angeordnet ist, und fährt dann erneut fort, die Bedingung zu prüfen. Wenn die Prüfung falsch zurückgibt, endet die Schleife und die folgenden Befehle werden ausgeführt: Erledigt. Das gilt es sicherzustellen<проверка условия>hing vom Code ab, der in der Schleife ausgeführt wird. Andernfalls erhalten Sie eine Endlosschleife, wenn sich das Ergebnis der Überprüfung nicht ändert.
Die Standardeingabe für eine While-Schleife kann mithilfe des Umleitungsbefehls in eine Datei umgeleitet werden< в конце цикла.

Syntax:
während<Проверка условия>
Tun
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
Erledigt

Beispiel:
während [ $var0 -eq 100 ]
Tun
echo $var
var++
Erledigt

Operator während kann mehrere Bedingungen haben. Aber nur der letzte von ihnen bestimmt die Möglichkeit, den Zyklus fortzusetzen. In diesem Fall unterscheidet sich die Syntax der Schleifenanweisung von der üblichen.
Syntax(Ich wiederhole noch einmal, dass nur die letzte Bedingung die Ausführung der Schleife beeinflusst) :
während
<условие1>
<условие2>

<условиеN>
Tun
<выполняемые команды - тело цикла>
Erledigt

bis Schleife:

Operator bis Sehr ähnlich wie while, wertet es auch die Bedingung aus, führt aber den Rumpf der Schleife aus, wenn das Ergebnis der Berechnung falsch ist. Es mag seltsam erscheinen, aber until wertet die Bedingung vor der ersten Iteration der Schleife aus, wie while, und nicht danach. Wie bei for/in-Schleifen müssen Sie, wenn Sie das do-Schlüsselwort in derselben Zeile wie die Schleifendeklaration platzieren, das Zeichen „;“ einfügen. vorher tun.
Wie im vorherigen Fall ist es wichtig, daran zu denken, dass die Bedingung von den Operationen im Schleifenkörper abhängen muss, sonst wird unser Skript nie enden.

Syntax:
bis<Проверка условия>
Tun
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
Erledigt

Beispiel:
until [ $var0 -gt 100] # Die Bedingung wird zu Beginn der Iteration geprüft.
Tun
echo $var
var--
Erledigt

Wahrscheinlich genug für jetzt. :)

  • zurück
  • Nach vorne

Neue Artikel:

  • Die Netzwerkerkennung wird in Windows 7/8/2008/2012 nicht aktiviert
  • Fehler: Diese Anwendung konnte nicht gestartet werden, weil sie das Qt-Plattform-Plugin „Windows“ nicht finden oder laden konnte.
  • Konfigurieren des automatischen Neustarts von Arbeitsprozessen rphost.exe server 1C 8.3
  • So reduzieren Sie die Größe des Transaktionsprotokolls (.ldf) in MS SQL 2008/20012

    MS SQL führt wie jedes anständige industrielle DBMS zusammen mit der Datenbank Transaktionsprotokolle, mit denen Sie den Status zurücksetzen können ...

5

Ihr Skript ist auf gefährliche Weise codiert.

Erstens gehe ich davon aus, dass Sie die Bash-Shell verwenden, da Sie sie mit "/bash" und "/for" markiert haben.

In meiner Antwort werde ich diesen großartigen Bash-Leitfaden zitieren, der wahrscheinlich die beste Quelle zum Erlernen von Bash ist.

1) Verwenden Sie niemals Command Substitution , out oder freundlich, ohne Anführungszeichen. Hier gibt es ein großes Problem: Verwenden einer Erweiterung ohne Anführungszeichen, um die Ausgabe in Argumente aufzuteilen.

Genauer gesagt werden diese $(find$ DIRWORK -type d -name work) und $(find$ DIR -type f) Word Splitting unterzogen, wenn also find eine Datei mit Leerzeichen im Namen findet, d.h. das Wort "filename" wird aufgeteilt Das Ergebnis von Bash übergibt 2 Argumente an den for-Befehl, über den iteriert werden soll, dh eines für "Datei" und eines für "Name". In diesem Fall möchten Sie hoffen, dass Sie "Datei: keine solche Datei oder kein solches Verzeichnis" und "Name: keine solche Datei oder kein solches Verzeichnis" erhalten, anstatt sie möglicherweise zu beschädigen, wenn sie existieren.

2) Per Konvention werden Umgebungsvariablen (PATH, EDITOR, SHELL, ...) und interne Shell-Variablen (BASH_VERSION, RANDOM, ...) vollständig großgeschrieben. Alle anderen Variablennamen müssen in Kleinbuchstaben geschrieben werden. Da bei Variablennamen zwischen Groß- und Kleinschreibung unterschieden wird, vermeidet diese Konvention eine versehentliche Neudefinition von Umgebungs- und internen Variablen.

Dies ist eine sicherere Version Ihres Skripts, die ich Ihnen stattdessen empfehle:

My_home="/root/mydir" my_dir=" $my_home/var" dir_work="$ my_home/Local" while IFS= read -r -d "" f; do # Ich vermute, dass Sie auch stderr ignorieren möchten; # hierher kommt 2>&1. if lsof -n " ​​​​$f" | grep "" > /dev/null 2> then echo "hey , ich "bin jetzt sicherer!" fi fertig< <(find "$ dir_work" -type f -print0) while IFS= read -r -d "" f; do echo "2" done < <(find "$dir_work" -type d -name "work" -print0)

Wie Sie sehen können, ist die IFS-Variable auf leer gesetzt, wodurch verhindert wird, dass read die führenden und nachgestellten Leerzeichen aus der Zeichenfolge entfernt. Der Lesebefehl verwendet die leere Zeichenfolge (-d "") als Trennzeichen, um zu lesen, bis er eine \ 0 erreicht. find muss jeweils m sein, also verwendet er die Option -print0, um seine Daten mit \ 0 anstelle eines Zeilenumbruchs zu begrenzen. was überraschenderweise und böswilligerweise Teil des Dateinamens sein kann. Das Aufteilen einer solchen Datei in \n zwei Teile wird unseren Code brechen.

Die vorherige Antwort, die besagt, dass find ... | während Lesename; Tun ...; done sollte verwendet werden, um find s zu lesen, die Ausgabe kann auch schlecht sein. Die While-Schleife wird in einer neuen Subshell ausgeführt, wobei ihre Kopie der Variablen von der übergeordneten Shell kopiert wird. Diese Kopie wird dann für beliebige Zwecke verwendet. Wenn die While-Schleife beendet ist, wird die Kopie der Subshell verworfen und die ursprünglichen Variablen der Eltern werden nicht geändert.

Wenn Sie beabsichtigen, einige Variablen innerhalb dieser While-Schleife zu ändern und sie später in der übergeordneten Schleife zu verwenden, sollten Sie ein sichereres Skript verwenden, das Datenverlust verhindert.

0

"Verwenden Sie niemals Command Substitution, gleich welcher Art, ohne Anführungszeichen." Es ist nur Spitzfindigkeit, aber es ist möglich, Befehlsersetzungen ohne Anführungszeichen zu verwenden, wenn Sie eine Variable setzen: "etwas = $(Basisname" Dateiname mit Leerzeichen ")". - Schmied John 22. Apr. 13 2013-04-22 21:43:10

2

For i in $(find$ DIRWORK -type d -name work); do echo "2" fertig

wird der erste sein, der diese Zeile ausführt

Suchen Sie $DIRWORK -type d -name work

Warten Sie, bis find die Ausführung beendet hat, und nehmen Sie dann die Ausgabe und fügen Sie sie wieder in die for-Schleife ein

Für i in der Ausgabe von find; do echo "2" fertig

erst dann beginnt die Ausführung der for-Schleife.

Wenn find also lange braucht, um die for-Schleife abzuschließen, muss es lange warten, bevor es beginnen kann.

Probieren Sie temporäre Suchbefehle interaktiv aus

$ time find $DIRWORK -type d -name work

und sehen, wie lange es dauert.

Beachten Sie auch, dass Sie keine for-Schleife verwenden sollten, um Dateinamen zu durchlaufen. Verwenden Sie eine While-Schleife mit read , wie folgt:

Find$ DIRWORK -type d -name work | während Lesename; do echo "2" fertig

Bonus: Es führt die while-Schleife parallel zu find aus. Das bedeutet, dass die While-Schleife eine Iteration ausführt, sobald find eine Zeile ausgibt. Sie müssen nicht auf find warten, um die Ausführung abzuschließen.

mob_info