Fordern Sie den Benutzer in einer While-Schleife zur Eingabe eines Dateityps auf

Fordern Sie den Benutzer in einer While-Schleife zur Eingabe eines Dateityps auf

Ich passe ein Skript so an, dass es den Benutzer nach einer Datei eines bestimmten Typs fragt. Wenn die eingegebene Datei nicht dem bestimmten Dateityp entspricht, geht es in eine While-Schleife und wiederholt sich, bis der Benutzer die richtige Datei eingibt.

In diesem Fall fordere ich den Benutzer auf, eine .zipDatei in:

read -p "Enter zip file: " package1
 while [ package1 != *.zip ] ; do
     read -p "Please enter file ending in '.zip': " package1
 done <<< package1
echo $package1

Bis jetzt hatte ich Fehler. Jetzt bekomme ich nur einen leeren Cursor, keine Ausgabe. Unabhängig davon, ob ich etwas eingebe *.zipoder nicht, geht es mit einem leeren Cursor und ohne Ausgabe zur nächsten Zeile über.

Gedanken?

BEARBEITEN:

Okay, ich habe mich für die selectSchleife entschieden und das ist eine viel bessere Option als whilein diesem Fall.

Aber was wäre, wenn sich diese zipDatei (oder ein beliebiger anderer Dateityp) in einem anderen Verzeichnis befinden könnte? Ich möchte die Möglichkeit haben, in der select-loopShell Verzeichnisse zu wechseln.

Ich habe bisher versucht:

echo Select zip file:
                options=(".." *.zip)
                select package1 in "${options[@]}" ; do
                        case $package1 in
                                1 ) cd ..; echo Select zip file: ;;
                                # Different Directory ) ;;
                                * ) break ;;
                        esac
                done

Aber die Schleife zeigt die Menüelemente nach dem Verzeichniswechsel nicht erneut an. Ich bin mir nicht sicher, wie ich dem Benutzer cdeinen völlig anderen Pfad anbieten kann, außer ../wenn er möchte, und auch nicht, was ich dafür verwenden soll.

"All other existing \# file items" ) ... ; break;;

Innencase

Antwort1

Machen Sie es logisch einfacher, indem Sie nur die letzte Erweiterung untersuchen:

while [ "${package1##*.}" != "zip" ]
do
    read -e -p "Specify a .zip file: " package1
done
echo $package1

Antwort2

Es wurde eine elegantere Lösung gepostet, aber ich denke, es ist wichtig, auf einige der Fehler hinzuweisen, die dazu führen, dass Ihr ursprüngliches Skript fehlschlägt, und wie man sie behebt.

Wenn Sie die Variable in Ihrer While-Schleife testen package1, müssen Sie $zunächst das davor setzen, um die tatsächlichen Daten zu lesen, die in dieser Variablen gespeichert sind.

Verwenden Sie als nächstes [[...]]anstelle von [...]in Ihrem while-Schleifentest, da dies Ihnen ermöglicht, das Mustervergleichsmuster mit Ihrem Platzhalter durchzuführen *. Dies funktioniert jedoch nur in Bash, nicht in SH. Bitte beachten SieDasAntwort für eine ausführliche Erklärung der Verwendung von [[...]]versus [...].

<<< package1Schließlich müssen Sie die Zeichenfolge am Ende Ihrer While-Schleife nicht übergeben .

Hier ist eine geänderte Version Ihres Skripts, die wie vorgesehen funktioniert.

#!/bin/bash

read -p "Enter zip file: " package1
while [[ "$package1" != *.zip ]]; do
    read -p "Please enter file ending in '.zip': " package1
    done 
echo $package1

Antwort3

Lassen Sie den Benutzer niemals Dateipfadnamen interaktiv eingeben. Es ist einfacher für sie, Ihr Skript mit den Pfadnamen ihrer Zip-Archivdateien in der Befehlszeile des Skripts aufzurufen. Auf diese Weise können sie die Dateinamenvervollständigungsfunktion und die Dateinamen-Globbing-Muster der Shell verwenden.

Das Skript wird beispielsweise aufgerufen mit

./myscript /some/path/myarchive.zip

oder

./myscript folder/archive-*.zip

o.ä.

Im Skript würden Sie Folgendes tun:

#!/bin/bash

for archive_path do
    printf 'Processing archive "%s"...\n' "$archive_path"

   # code to process "$archive_path" goes here
done

Die Schleife im Skript würde alle an das Skript übergebenen Argumente durchlaufen und "$archive_path"würde in jeder Iteration den Pfadnamen eines einzelnen an das Skript übergebenen Archivs enthalten.

Es ist nicht nötig zu prüfen, ob der Name der "$archive_path"Datei mit einer bestimmten Zeichenfolge endet, da die Tools, die Sie für das Archiv verwenden, sich möglicherweise nicht einmal für das Dateinamensuffix interessieren. Wenn dies der Fall ist, schlagen sie mit dem entsprechenden Exit-Code fehl, den Sie leicht abfangen können:

if ! unzip "$archive_path"; then
    printf 'Failed to run unzip on "%s"\n' "$archive_path" >&2
    exit 1
fi

Wenn Sie es set -eim Skript verwenden (wahrscheinlich als erste Anweisung), wird es automatisch beendet, wenn ein beliebiger Befehl (der nicht Teil einer bedingten Anweisung ist) mit einem Exit-Code ungleich Null zurückkehrt.

set -e

# The following would terminate the script if it failed:
unzip "$archive_path"

Zu Ihrer hinzugefügten „Bearbeitung“: Was Sie dort tun, ist, ein Dateibrowser-Tool oder einen Dateimanager zum Auswählen von Zip-Archiven zu implementieren. Je nachdem, wofür Sie diesen Code tatsächlich verwenden möchten, ist dies möglicherweise übertrieben.

Antwort4

Wenn Sie möchten, dass der Benutzer eine der folgendenbestehendeDateien würde ich selectanstelle von verwenden read, um dem Benutzer die Auswahl aus einer Liste zu ermöglichen, anstatt einen Dateinamen zu schreiben, den er möglicherweise nicht genau kennt.

select package1 in *.zip; do
    break;
done
echo "$package1"

Dem Benutzer wird eine Liste angezeigt und er gibt die Nummer ein.

verwandte Informationen