Bash shell 脚本,以 $1 作为带有通配符的变量

Bash shell 脚本,以 $1 作为带有通配符的变量

我有一个基本的 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.txtfile2.txtfile3.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

相关内容