ls mit glob funktioniert nicht in einem Bash-Skript


10

Ich muss alle Unterverzeichnisse eines Verzeichnisses auflisten, mit Ausnahme derjenigen, die mit einer Liste übereinstimmen, die als Argument angegeben wurde: "SUBDIR1, SUBDIR2, ..., SUBDIRN".

Ich kam mit der Lösung (aus vielen Quellen), ls mit einem Glob-Muster zu verwenden. Um das Konzept zu testen, habe ich in der Befehlszeile die folgende Sequenz ausprobiert, die zu funktionieren scheint:

DIR="/path/to/dirs"
EXCLUDELIST="subdir1,subdir2"
#transform in a glob pattern for excluding given subdirectories
EXCLUDE="!(${EXCLUDELIST//,/|})"
LIST=$(cd $DIR && ls -l -d $EXCLUDE | grep -E "(^d)" | awk '{print $9}')

Wenn ich es jedoch unverändert in ein Bash-Skript einfüge , wird dieser Fehler angezeigt

ls: cannot access !(subdir1|subdir2): No such file or directory

Was mache ich falsch, wenn ich diesen Code in das Skript einfüge?

Antworten:


3

Dennis hat Ihnen erklärt, warum Ihr Skript fehlschlägt, aber ich möchte einen einfacheren (und sichereren) Weg vorschlagen, dies zu tun. Das Parsen lsist fast immer eine schlechte Idee , es kann leicht zu Dateinamen mit Leerzeichen oder neuen Zeilen oder anderen seltsamen Zeichen führen und ist in den LOCALE-Einstellungen nicht portierbar. Außerdem ist Ihr Befehl sehr komplex und umfasst mehrere Schritte. Warum nicht alles in find?

DIR="/path/to/dirs"
EXCLUDELIST="subdir1,subdir2"
## Build the regular expression
EXCLUDE="${EXCLUDELIST//,/|.*}"
LIST=$(find "$DIR" -type d -regextype posix-awk -not -regex ".*$EXCLUDE.*")

By the way, wird das Skript nicht , wie Sie es geschrieben haben , weil Sie die glob bauen vor cd -ing in $DIRso wird es in Bezug auf den Inhalt des aktuellen Verzeichnisses gebaut werden.


Danke, es funktioniert, muss nur -printf "% f \ n" hinzufügen, um nur den Unterverzeichnisnamen (nicht den gesamten Pfad) zu erhalten. Übrigens ist das CD-Erstellen vor dem Glob beabsichtigt und funktioniert im interaktiven Modus.
Pablochacin

10

Interaktive und nicht interaktive Bash-Shells verhalten sich nicht gleich. Einer der vielen Unterschiede besteht darin, dass die Shell-Option extglob standardmäßig für interaktive Shells aktiviert ist (zumindest in meiner Version von bash), jedoch nicht für nicht interaktive.

Aktivieren Sie extglob mit dem folgenden Befehl , um Ihr Skript zu reparieren :

shopt -s extglob

Durch Aktivieren dieser Option hat die Shell den Glob vor dem Ausführen des Befehls ls erweitert: ls -1 -d subdir3 subdir4 subdir5 ..... subdirn wobei die Liste der Unterverzeichnisse die tatsächliche Erweiterung des Glob ist.
Pablochacin

Ja, so funktionieren Globs. Ich glaube nicht, dass ich verstehe, was Sie damit meinen.
Dennis

Der Befehl shopt funktioniert in #!/bin/bashSkripten, jedoch nicht in #!/bin/sh(was auf meinem RHEL6-System tatsächlich Bash ist, aber die Verwendung dieses Namens weist es an, ein anderes Verhalten zu verwenden). Mein Google-Fu versagt mir, ich kann den entsprechenden Bourne-Shell-Befehl nicht finden.
Dan Pritts
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.