Wie listet man alle Dateien eines Verzeichnisses zusammen mit einem Index auf, damit Benutzer Dateien durch Eingabe der Indexnummer auswählen können?

Wie listet man alle Dateien eines Verzeichnisses zusammen mit einem Index auf, damit Benutzer Dateien durch Eingabe der Indexnummer auswählen können?

Ich habe mehrere Dateien in einem Verzeichnis und arbeite an einem Bash-Skript, um alle Dateien zusammen mit einem Index daneben aufzulisten, sodass die Benutzer anhand des Indexes auswählen können, welche Datei sie auswählen möchten, anstatt den gesamten Dateinamen zu schreiben.

Zum Beispiel:

main_dir
 - temp_1
 - temp_2

Mein Versuch:

while [[ 1 ]]; do
        printf "Which file do you want to use? ($(ls -m ${main_dir})) "
        read -r ans
        if [[ -d ${main_dir}/${ans} ]]; then
            break
        else
            echo "[ERROR] Failed to choose. Please choose from ($(ls -m "${main_dir}"))."
        fi
    done

In diesem Fall lautet die Ausgabe:

Which file do you want to use? (temp_1, temp_2)

Außerdem muss der Benutzer den Namen der Datei eingeben, um sie auszuwählen.

ERWARTETES ERGEBNIS:

Which file do you want to use? 
1. temp_1 
2. temp_2

Außerdem sollte der Benutzer eine Datei auf beide Arten auswählen können: durch Eingabe des Namens oder des Index.

Antwort1

Schleife über * und merke dir die Dateien in einem Array:

files=()
i=0
for f in *
do 
  [ -d "$f" ] && continue ## skip directoriries
  files[$i]="$f"
  echo "$i"$'\t'"${files[i]}"
  (( ++i ))
done
if read -p "Which file do you want to use? " ans 
then 
     echo "you choose ${files[ans]}"
     stat "${files[ans]}"
     wc "${files[ans]}"
fi

Antwort2

Erweiterung des Kommentars von @Cyrus zur Nützlichkeit der Bash- selectDirektive …

Wenn Ihre Bedingung, nach Nummer oder Name auswählen zu können, nicht wäre, selectwäre die Option von Bash möglicherweise alles, was Sie brauchen:

$ select name in *; do printf "You chose %s\n" "$name"; done
1) file AA    6) file_E   11) file_J   16) file_O   21) file_T   26) file_Y
2) file_A     7) file_F   12) file_K   17) file_P   22) file_U   27) file_Z
3) file_B     8) file_G   13) file_L   18) file_Q   23) file_V   28) foo.sh
4) file_C     9) file_H   14) file_M   19) file_R   24) file_W
5) file_D    10) file_I   15) file_N   20) file_S   25) file_X
#? 1
You chose file AA
#? 4
You chose file_C
#? 28
You chose foo.sh
#? ^D

selectObwohl die Benutzeroberfläche für manche Zwecke etwas spartanisch sein könnte, ist es ein nützliches Werkzeug, das man in der Tasche haben sollte, wenn man etwas Schnelles und Einfaches braucht, das aber dennoch zuverlässig ist .

Auf der manSeite für Bash werden einige Aspekte des selectVerhaltens von aufgeführt, die wir nutzen können:

Anschließend wird die PS3-Eingabeaufforderung angezeigt und eine Zeile aus der
Standardeingabe gelesen. Wenn die Zeile aus einer Zahl besteht, die
einem der angezeigten Wörter entspricht, wird der Wert von name auf
dieses Wort gesetzt. Wenn die Zeile leer ist, werden die Wörter und die Eingabeaufforderung
erneut angezeigt. Wenn EOF gelesen wird, wird der Befehl abgeschlossen. Jeder
andere gelesene Wert führt dazu, dass name auf null gesetzt wird. Die gelesene Zeile
wird in der Variablen REPLY gespeichert.

Indem wir den Aufruf von mit etwas unterstützendem Code umgeben select, ist Folgendes möglich:

unset name

_PS3="$PS3"
PS3="Which file do you want to use? "

while [ -z "$name" ]
do

    select name in *; do break; done

    if [ -z "$name" ]
    then
        if [ -f "$REPLY" ]
        then
            name="$REPLY"
            printf "You chose by name: '%s'\n" "$name"
        else
            printf "There is no file by that name.\n"
        fi
    else
        printf "You chose by number: '%s'\n" "$name"
    fi

done

PS3="$_PS3"; unset _PS3

Ausgabe:

$ ./foo.sh 
1) file AA    6) file_E   11) file_J   16) file_O   21) file_T   26) file_Y
2) file_A     7) file_F   12) file_K   17) file_P   22) file_U   27) file_Z
3) file_B     8) file_G   13) file_L   18) file_Q   23) file_V   28) foo.sh
4) file_C     9) file_H   14) file_M   19) file_R   24) file_W
5) file_D    10) file_I   15) file_N   20) file_S   25) file_X
Which file do you want to use? 12
You chose by number: 'file_K'
$ ./foo.sh 
1) file AA    6) file_E   11) file_J   16) file_O   21) file_T   26) file_Y
2) file_A     7) file_F   12) file_K   17) file_P   22) file_U   27) file_Z
3) file_B     8) file_G   13) file_L   18) file_Q   23) file_V   28) foo.sh
4) file_C     9) file_H   14) file_M   19) file_R   24) file_W
5) file_D    10) file_I   15) file_N   20) file_S   25) file_X
Which file do you want to use? file W
There is no file by that name.
1) file AA    6) file_E   11) file_J   16) file_O   21) file_T   26) file_Y
2) file_A     7) file_F   12) file_K   17) file_P   22) file_U   27) file_Z
3) file_B     8) file_G   13) file_L   18) file_Q   23) file_V   28) foo.sh
4) file_C     9) file_H   14) file_M   19) file_R   24) file_W
5) file_D    10) file_I   15) file_N   20) file_S   25) file_X
Which file do you want to use? 29
There is no file by that name.
1) file AA    6) file_E   11) file_J   16) file_O   21) file_T   26) file_Y
2) file_A     7) file_F   12) file_K   17) file_P   22) file_U   27) file_Z
3) file_B     8) file_G   13) file_L   18) file_Q   23) file_V   28) foo.sh
4) file_C     9) file_H   14) file_M   19) file_R   24) file_W
5) file_D    10) file_I   15) file_N   20) file_S   25) file_X
Which file do you want to use? file AA
You chose by name: 'file AA'

verwandte Informationen