我有一个基本的 bash 脚本,当前将指定文件的输入作为变量查找,如果它为空,则处理整个目录。
如果我在执行时指定一个文件,那么script.sh file1.txt
它会处理该文件。
我想要但无法弄清楚的是如何使用通配符指定多个文件。例如:
script.sh file*.txt
我想它需要一些简单的循环,但我找不到任何与此场景匹配的示例。
当我尝试执行循环时,它仅处理第一个匹配项。
#!/bin/bash
if [ $# -eq 0 ]; then
echo "no argument supplied, pulling all file from tick_tock"
for i in /var/tank/tick_tock/*.txt; do
cp "$i" /var/tank/awaiting/
done
fi
echo "you supplied $1"
cp "$1" /var/tank/awaiting/
答案1
如果您使用以下命令调用脚本:
$ script.sh file*.txt
如果存在匹配项,则 shell 会将该 glob 扩展到文件匹配列表。例如,假设您有file1.txt
、file2.txt
和file3.txt
,则上述命令相当于:
$ script.sh file1.txt file2.txt file3.txt
顺序可能不同,但这并不重要。
在这种情况下处理文件的一种选择是像这样的循环:
while [[ $# -ne 0 ]]; do
# process ${1}
shift
done
将shift
丢弃旧的${1}
和转移其余参数“左移”1(2 变为 1,3 变为 2,等等)。还shift
更新了$#
。
例如:
#!/bin/bash
while [[ $# -ne 0 ]]; do
echo ${1}
shift
done
如果我运行该脚本,我会看到:
$ ./script.sh a b c
a
b
c
$
答案2
这里的问题是通配符模式扩展到多种的参数,而不仅仅是 处的单个参数$1
。其他的位于 、 等中$2
。$3
您无法对那些具有标准 shell 功能的索引进行索引,但通常不需要:您可以使用 访问脚本的参数列表"$@"
。所以:
if [ "$#" -eq 0 ]; then
echo "no arguments"
else
echo "$# arguments:"
for x in "$@"; do
echo " $x" # or do whatever with $x
done
fi
类似的东西cp -- "$@" /var/tank/awaiting/
会依次调用cp
脚本作为参数获得的文件。 There--
阻止任何以下参数被视为 的选项cp
。