如何列出目錄中的所有文件並附上索引,以便使用者透過輸入索引號來選擇檔案?

如何列出目錄中的所有文件並附上索引,以便使用者透過輸入索引號來選擇檔案?

我在一個目錄中有多個文件,我正在編寫一個 bash 腳本來列出所有文件以及它們旁邊的索引,以便用戶可以根據索引選擇要選擇的文件,而不是寫入整個文件名稱。

例如。

main_dir
 - temp_1
 - temp_2

我的嘗試:

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

在這種情況下,輸出是:

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

此外,使用者必須輸入檔案名稱才能選擇它。

預期結果:

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

並且,使用者應該能夠透過輸入名稱或索引兩種方式選擇檔案。

答案1

循環 * 並記住數組中的檔案:

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

答案2

擴展@Cyrus 關於 bash 指令的實用性的評論select...

如果不是因為您規定能夠按數字或名稱進行選擇,那麼 bashselect可能就是您所需要的:

$ 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

雖然介面對於某些需求來說可能有點斯巴達式,但當您需要一些快速而骯髒的東西,但外殼級可靠時,select這是一個可以放在包裡的有用工具。

bash 的頁面引用了我們可以利用的行為man的一些方面:select

然後顯示 PS3 提示符號並從標準輸入讀取一行
。如果該行包含
與顯示的單字之一相對應的數字,則名稱的值將設定
為該單字。如果該行為空,則再次顯示文字和提示
。如果讀取到 EOF,則命令完成。讀取任何
其他值都會導致 name 設定為 null。讀取的行
保存在變數 REPLY 中。

因此,透過在對 的呼叫周圍放置一些支援程式碼select,這是可能的:

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

輸出:

$ ./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'

相關內容