for i in $(ls);do
if [ $i = '*.java' ];then
echo "I do something with the file $i"
fi
done
Ich möchte jede Datei im aktuellen Ordner durchlaufen und prüfen, ob sie mit einer bestimmten Erweiterung übereinstimmt. Der obige Code funktioniert nicht, wissen Sie warum?
for i in $(ls *.java); do echo "do something with file $i"; done
?$i
mit der Literalzeichenfolge "* .java"; Eine Mustererweiterung wird hier nicht durchgeführt.if [[ $i == *.java ]]; then
.., um die if-Anweisung so zu korrigieren, wie Sie sie haben (beachten Sie die doppelten [[]] s und die nicht zitierte * .java).ls
Analysieren Sie nicht - akzeptieren Sie die Antwort von @ chepnerAntworten:
Keine ausgefallenen Tricks nötig:
Der Guard stellt sicher, dass die Schleife beendet wird, wenn keine übereinstimmenden Dateien vorhanden sind, ohne zu versuchen, einen nicht vorhandenen Dateinamen zu verarbeiten
*.java
. Inbash
(oder Shells, die etwas Ähnliches unterstützen) können Sie dienullglob
Option verwenden, um eine fehlgeschlagene Übereinstimmung einfach zu ignorieren und nicht in den Hauptteil der Schleife einzutreten.quelle
for i in *.java *.cpp; do
. Wenn Sie Muster in aktiviert erweitertbash
mitshopt -s extglob
, können Sie schreibenfor i in *.@(java|cpp); do
.shopt -s nullglob
damit ein nicht übereinstimmendes Muster zur leeren Sequenz erweitert wird, anstatt wörtlich behandelt zu werden.cd
in dieses Verzeichnis gehen, bevor Sie diefor
Schleife startennullglob
, dass es als leere Sequenz behandelt wird, oderfailglob
dass es als Fehler behandelt wird. (Wenn Sie beide setzen,failglob
hat Vorrang.)Die richtige Antwort lautet @ chepner's
Hier ist jedoch ein kleiner Trick, um zu überprüfen, ob ein Dateiname eine bestimmte Erweiterung hat:
quelle
ext
statt.java
?Rekursiv Unterordner hinzufügen,
quelle
find . -name "*.java" -type f -exec echo \{\} \;
zu vermeiden, dass die Ausgabe vonfind
"$i"
innerhalb der Schleife zitieren .Schleife durch alle Dateien mit der Endung:
.img
,.bin
,.txt
Suffix und die Dateinamen drucken:Oder rekursiv (auch in allen Unterverzeichnissen zu finden):
quelle
Ich stimme den anderen Antworten bezüglich der richtigen Art und Weise zu, die Dateien zu durchlaufen. Das OP fragte jedoch:
Ja!
Ein ausgezeichneter Artikel Was ist der Unterschied zwischen test, [und [[?] Erklärt ausführlich, dass Sie unter anderem den Befehl nicht verwenden können
expression matching
oderpattern matching
innerhalb destest
Befehls (was eine Abkürzung für ist[
)Dies ist der Grund, warum Ihr Skript fehlschlägt. Wenn das OP an einer Antwort mit der
[[
Syntax interessiert ist (was den Nachteil hat, dass sie nicht auf so vielen Plattformen wie der[
Befehl unterstützt wird), würde ich meine Antwort gerne bearbeiten, um sie einzuschließen.BEARBEITEN: Alle Protips zum Formatieren der Daten in der Antwort als Tabelle wären hilfreich!
quelle
Wie @chepner in seinem Kommentar sagt, vergleichen Sie $ i mit einer festen Zeichenfolge.
Um die Situation zu erweitern und zu korrigieren, sollten Sie [[]] mit dem regulären Ausdrucksoperator = ~ verwenden
z.B:
Die Regex rechts von = ~ wird gegen den Wert des linken Operators getestet und sollte nicht in Anführungszeichen gesetzt werden (Anführungszeichen werden nicht fehlerhaft sein, sondern mit einer festen Zeichenfolge verglichen und daher höchstwahrscheinlich fehlschlagen.)
Die obige Antwort von @chepner mit glob ist jedoch ein viel effizienterer Mechanismus.
quelle
ext
statt.java
?if [[ $i == *.java ]]
oderif [[ $i == *.$ext ]]
. Aber analysieren Sie nicht lsIch fand diese Lösung sehr praktisch. Es verwendet die
-or
Option infind
:find . -name \*.tex -or -name "*.png" -or -name "*.pdf"
Es werden die Dateien mit der Erweiterung finden
tex
,png
undpdf
.quelle