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 .zip
Datei 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 *.zip
oder nicht, geht es mit einem leeren Cursor und ohne Ausgabe zur nächsten Zeile über.
Gedanken?
BEARBEITEN:
Okay, ich habe mich für die select
Schleife entschieden und das ist eine viel bessere Option als while
in diesem Fall.
Aber was wäre, wenn sich diese zip
Datei (oder ein beliebiger anderer Dateityp) in einem anderen Verzeichnis befinden könnte? Ich möchte die Möglichkeit haben, in der select-loop
Shell 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 cd
einen 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 [...]
.
<<< package1
Schließ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 -e
im 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 select
anstelle 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.