我正在调整一个脚本,以便它会询问用户特定类型的文件。如果输入的文件与特定文件类型不匹配,则进入 while 循环并重复,直到用户输入正确的文件。
在本例中,我要求用户提供以下.zip
位置的文件:
read -p "Enter zip file: " package1
while [ package1 != *.zip ] ; do
read -p "Please enter file ending in '.zip': " package1
done <<< package1
echo $package1
到目前为止我一直有错误。现在,我只是得到一个空白光标,没有输出。无论我是否输入*.zip
,它都会进入下一行,光标为空白,没有输出。
想法?
编辑:
好吧,我决定使用循环,这是比本例select
更好的选择。while
但是,如果该zip
文件(或提示的任何文件类型)可能位于任何其他目录中怎么办?我希望它能够在 shell 中提供更改目录的选项select-loop
。
到目前为止我尝试过:
echo Select zip file:
options=(".." *.zip)
select package1 in "${options[@]}" ; do
case $package1 in
1 ) cd ..; echo Select zip file: ;;
# Different Directory ) ;;
* ) break ;;
esac
done
但更改目录后循环不会重新显示菜单项。我不知道如何为用户提供cd
完全不同的路径,除非../
他们想要,也不知道用于什么
"All other existing \# file items" ) ... ; break;;
代替case
答案1
通过仅检查最终扩展,使其在逻辑上更容易:
while [ "${package1##*.}" != "zip" ]
do
read -e -p "Specify a .zip file: " package1
done
echo $package1
答案2
已经发布了一个更优雅的解决方案,但我认为指出一些导致原始脚本失败的错误以及如何修复它们很重要。
首先,当您在 while 循环中测试变量时package1
,需要将 放在$
它前面,以便读取该变量中存储的实际数据。
接下来使用[[...]]
而不是[...]
在 while 循环测试中使用,因为这允许您使用通配符进行模式匹配*
。但是,这只适用于 bash,不适用于 sh。请参见这[[...]]
回答使用vs的完整解释[...]
。
最后,您不需要<<< package1
在 while 循环末尾传递字符串。
这是脚本的修改版本,可以按预期工作。
#!/bin/bash
read -p "Enter zip file: " package1
while [[ "$package1" != *.zip ]]; do
read -p "Please enter file ending in '.zip': " package1
done
echo $package1
答案3
永远不要让用户以交互方式输入文件的路径名。他们可以更轻松地在脚本的命令行上使用其 Zip 存档文件的路径名来调用您的脚本。这允许他们使用 shell 的文件名完成工具和文件名通配模式。
该脚本将使用例如调用
./myscript /some/path/myarchive.zip
或者
./myscript folder/archive-*.zip
或类似的。
在脚本中,你会做
#!/bin/bash
for archive_path do
printf 'Processing archive "%s"...\n' "$archive_path"
# code to process "$archive_path" goes here
done
脚本中的循环将循环传递给脚本的所有参数,并且在每次迭代中,"$archive_path"
将是传递给脚本的单个存档的路径名。
无需检查文件名是否"$archive_path"
以任何特定字符串结尾,因为您在存档上使用的工具甚至可能不关心文件名后缀。如果他们这样做,那么他们会失败并显示适当的退出代码,您可以轻松捕获该退出代码:
if ! unzip "$archive_path"; then
printf 'Failed to run unzip on "%s"\n' "$archive_path" >&2
exit 1
fi
如果您set -e
在脚本中使用(可能作为其第一条语句),则当任何命令(不是条件语句的一部分)返回非零退出代码时,它将自动退出。
set -e
# The following would terminate the script if it failed:
unzip "$archive_path"
关于您添加的“编辑”:您正在做的事情是开始实现文件浏览器工具或文件管理器来选择 Zip 存档。根据您实际想要使用此代码的目的,这很可能是多余的。
答案4
如果您希望用户从中选择一项现存的文件,我会使用select
,read
来让用户从列表中进行选择,而不是编写他可能不完全知道的文件名。
select package1 in *.zip; do
break;
done
echo "$package1"
用户将看到一个列表并输入号码。