Dateien auflisten und in Variablen speichern

Dateien auflisten und in Variablen speichern

Ich bin neu in der Shell-Programmierung. Mein Ziel ist es, dem Benutzer eine Auswahl zu geben, welche Datei ausgeführt werden soll. Ich fange alle verfügbaren Skripte in einer Variable ab mit:

var=$(find script*)

so weit, so gut, das ist die Ausgabe:

    echo $var
    script1 script2 script3 scr...

jetzt möchte ich jede Datei in einer einzelnen Variable speichern, um sie bei einer späteren Auswahl auszuführen

select SEL in script1 script2 script3 ..........
case $SEL in
        $Script1) echo ($Script1 will start) && ./$script1 ;;
        $Script2) echo ($Script2 will start) && ./$script2 ;;
        $Script3) echo ($Script3 will start) && ./$script3 ;;
        $Sc..) echo ($Scr.... will start) && ./$scrip.... ;;
        $Sc...) echo ($Sc...... will start) && ./$scrip..... ;;
        *) echo "choose on of the availabel files";;
    esac
done

Ich habe keine Ahnung, wie ich alle Dateien trennen soll, wenn ich nicht weiß, wie viele es sind und wie lang jede Datei genau ist.

Ich habe versucht, mit echo ${var[1]} und echo $var[1] zu teilen, aber das funktioniert nicht. Ich erhalte entweder eine leere Ausgabe oder den gesamten String.

Antwort1

Ihre erste Zeile:

var=$(find script*)

ist nur die Erstellung vareiner einzelnen String-Variable mit allen script*darin. Es istnichtein Array, daher können wir es nicht wie []gewünscht indizieren.

Das script*wird tatsächlich von der Shell erweitert, findtut also nichts (es sei denn, es handelt sich um Verzeichnisse, was aber nicht der Fall zu sein scheint) – es erhält lediglich alle Dateinamen als Argumente, prüft deren Existenz und gibt sie direkt wieder aus. Die Shell erledigt tatsächlich die ganze Arbeit.

Stattdessen können wir eineAnordnung, und wir können die Shell verwendenGlob-Erweiterungdirekt, um es zu füllen:

files=(script*)

Wenn wir den Initialisierer (die rechte Seite des =) in Klammern setzen, erstellen wir ein Array, das mehrere Werte separat enthält. script*wird auf jeden Dateinamen erweitert, der scriptim aktuellen Verzeichnis mit beginnt. Wenn die Dateinamen Leerzeichen enthalten, führen diese nicht dazu, dass die Wörter so aufgeteilt werden, wie dies bei Befehlen (Backticks oder $()) innerhalb des Array-Initialisierers der Fall wäre.

An dieser Stelle können wir einige Benutzereingaben einlesen:

select SEL in "${files[@]}"
do
    if ! [ "$SEL" ]
    then
        echo "Choose one of the available files."
        continue
    fi
    echo "$SEL will start"
    "./$SEL"
    break
done

Wir schreiben, "${files[@]}"um unser gesamtes Array von Dateinamen sauber zu erweitern, um es an zu geben select. Dem Benutzer wird eine Auswahl an Dateien angeboten, und dann betreten wir den do...doneBlock.

Wenn $SELleer ist, hat der Benutzer einen nicht vorhandenen Eintrag ausgewählt. Daher drucken wir die Eingabeaufforderung aus und continueder Benutzer wird gebeten, erneut auszuwählen.

Andernfalls erhalten wir echodie Benachrichtigung, dass das Skript gestartet wird, und führen das Skript aus. Wir setzen den Namen in Anführungszeichen "./$SEL", falls der Skriptname Leerzeichen enthält, was andernfalls dazu führen würde, dass der Befehlsname als ./firstwordmit den verbleibenden Wörtern als Argumenten behandelt würde. breakverhindert, dass wir zurückgehen und den Benutzer erneut fragen müssen; wenn Sie das tun möchten, nehmen Sie es heraus.


Das case...ofvon Ihnen verwendete Skript scheint in dem von Ihnen angegebenen Beispiel keine große Wirkung zu haben, aber wenn Sie je nach gewähltem Skript ein separates Verhalten haben (und es muss inDasSkript), können Sie das innerhalb des do...doneBlocks einfügen.

Antwort2

Ich bin mir nicht 100% sicher, ob ich ganz verstehe, was Sie tun möchten, aber das könnte für Sie besser funktionieren: Anstelle von var=$(find script*) und einem Fall könnten Sie besser verwenden

for i in `find script*`
do
        echo ($i will start) 
        ./$i
done

verwandte Informationen