如何列出目录中的所有文件以及索引,以允许用户通过输入索引号来选择文件?

如何列出目录中的所有文件以及索引,以允许用户通过输入索引号来选择文件?

我在一个目录中有多个文件,我正在编写一个 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 关于 bashselect指令实用性的评论......

如果不是因为你的规定不能通过数字或名称进行选择,那么 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它就是一种很有用的工具。

manbash 的页面列举了我们可以利用的某些行为select方面:

然后显示 PS3 提示符并从标准输入中读取一行
。如果该行包含
与显示的单词之一相对应的数字,则将 name 的值设置
为该单词。如果该行为空,则再次显示单词和提示符
。如果读取了 EOF,则命令完成。
读取的任何其他值都会导致将 name 设置为空。读取的行
保存在变量 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'

相关内容