BASH 列出可能的文件并选择一个

BASH 列出可能的文件并选择一个

我希望能够运行 bash 脚本,让它列出可能的文件作为选择一个文件的选项,然后通过 scp 将该文件传输到目的地...

scp 部分没问题,但如何获取文件列表并能够选择一个文件对我来说是一个挑战......

$ ./script
Please select a file.
[0] ~/Desktop/ScreenShot-04-06-19-01:02:33.png
[1] ~/Desktop/ScreenShot-04-06-19-01:03:33.png
[2] ~/Desktop/ScreenShot-04-06-19-01:04:33.png
Enter File Index ID: 

答案1

另一种方法是使用 bash 中的 select :

$ cat myscript
PS3="Enter File Index ID: "
echo "Please select a file."
select file ; do
  [ "$file" ] &&
   {
     echo "$file"
     break
   } ||
   {
     echo "bad choice"
     break
   }
done

你这样称呼它:

myscript ~/Desktop/*.png

PS:将 script 重命名为 myscript 因为 script 是一个命令。
man script

答案2

要提供一个交互式菜单,bash用户可以在其中从多个文件路径名中进行选择,您可能需要使用如下内容:

#!/bin/bash

files=( "$HOME/Desktop/ScreenShot-"*.png )

PS3='Select file to upload, or 0 to exit: '
select file in "${files[@]}"; do
    if [[ $REPLY == "0" ]]; then
        echo 'Bye!' >&2
        exit
    elif [[ -z $file ]]; then
        echo 'Invalid choice, try again' >&2
    else
        break
    fi
done

# use scp to upload "$file" here

在这里,我们使用bash语句select来提供菜单,并使用PS3三级提示来提供自定义提示。

用户可以退出脚本,而无需通过在0提示符下输入从列表中选择文件。如果给出无效响应,用户将有另一次选择文件的机会。根据提示按 即可重新显示菜单Enter

循环内部的逻辑如何select制定并不那么重要,只要脚本在$REPLY(用户输入的实际值)为空时终止0并在$file(从数组中选取的值)为空时重试即可。另一种select声明体可能看起来像

if [[ $REPLY == "0" ]]; then
    echo 'Bye!' >&2
    exit
elif [[ -n $file ]]; then
    break
fi

echo 'Invalid choice, try again' >&2

文件名通过 shell glob 插入到命名数组中。您还可以使用以下命令从脚本的命令行获取相关文件

files=( "$@" )

在 POSIX shell 中,您通常无权访问命名数组或select.相反,你可以做类似的事情

#!/bin/sh

set -- "$HOME/Desktop/ScreenShot-"*.png

while true; do
    i=0
    for pathname do
        i=$(( i + 1 ))
        printf '%d) %s\n' "$i" "$pathname" >&2
    done

    printf 'Select file to upload, or 0 to exit: ' >&2
    read -r reply

    number=$(printf '%s\n' "$reply" | tr -dc '[:digit:]')

    if [ "$number" = "0" ]; then
        echo 'Bye!' >&2
        exit
    elif [ "$number" -gt "$#" ]; then
        echo 'Invalid choice, try again' >&2
    else
        break
    fi
done

shift "$(( number - 1 ))"
file=$1

# use scp to upload "$file" here

这是一个相当常见的输入循环,它会进行迭代,直到用户输入有效的条目(或直到0输入并且脚本退出)。每次输入错误时都会重新显示菜单。

路径名通过 shell glob 被带入位置参数列表中,就像在变bash体中一样,但菜单是手动打印的,每个输出的菜单条目都有一个递增的整数。

最后的shift会移走位置参数列表开头的条目,以便$1成为用户想要上传的路径名。

要改为使用命令行上给出的路径名,只需删除初始set命令即可。

答案3

这就是我在 bash 脚本中的做法(也可以在 POSIXsh脚本中使用):

echo 'Please select a file.'

n=0
for img in ~/Desktop/ScreenShot-*.png
do
    n=$((n+1))
    printf "[%s] %s\n" "$n" "$img"
    eval "img${n}=\$img"
done

if [ "$n" -eq 0 ]
then
    echo >&2 No images found.
    exit
fi

printf 'Enter File Index ID (1 to %s): ' "$n"
read -r num
num=$(printf '%s\n' "$num" | tr -dc '[:digit:]')

if [ "$num" -le 0 ] || [ "$num" -gt "$n" ]
then
    echo >&2 Wrong selection.
    exit 1
else
    eval "IMG=\$img${num}"
    echo Selected image is "$IMG"
fi

相关内容