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.