
我在一個目錄中有多個文件,我正在編寫一個 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'