Bash 脚本:不使用 $@ 或 $* 扩展参数

Bash script: expansion of argument not using $@ or $*

使用 $@ 您可以对 bash 中的文件列表进行操作。示例:

script.sh:

#!/bin/bash
list=$@
for file in $list; do _commands_; done

然后我可以用

调用这个程序
~/path/to/./script dir1/{subdir1/*.dat,subdir2/*}

这个论点将扩展到成为 $list 的许多论点。但现在我想要其他参数,比如说 1 美元、2 美元,而这个清单是 3 美元。所以我希望 dir1/{subdir1/*.dat,subdir2/*} 的扩展发生在脚本内部,而不是变成许多参数。在命令行上你可以这样做:

find dir1/{subdir1/*.dat,subdir2/*}

并获得所需的输出,即文件列表。所以我尝试了这样的事情:

arg1=
arg2=
list=$(find )
for file in $list; do _commands_; done
...

呼叫:

~/path/to/./script arg_1 arg_2 'dir1/{subdir1/*.dat,subdir2/*}'

但是没有成功。非常感谢有关如何使此列表扩展为脚本内的变量的一些帮助!:)

编辑:所以下面的答案给出了使用这些命令的解决方案:

arg1=""
arg2=""
shift 2

for f in "$@"; do echo "processing $f"; done;

但出于好奇,是否仍然可以在脚本中将字符串 dir1/{subdir1/*.dat,subdir2/*} 传递给 find 命令(或任何达到相同目的的方法),而不使用 $@,这样获取列表?这可能很有用,例如如果最好不要将列表作为第一个或最后一个参数,或者在某些其他情况下,即使它需要转义字符或引用参数。

您可以在脚本中加入以下代码:

arg1=""
arg2=""
shift 2

for f in "$@"; do echo "processing $f"; done;

然后将其命名为:

~/path/to/script arg_1 arg_2 dir1/{subdir1/*.dat,subdir2/*}

使用shift 2会将位置参数移动2个位置,从而使</code>成为<code></code>成为<code>等。然后您可以直接调用$@ 迭代其余参数。

根据help shift

shift: shift [n]

  Shift positional parameters.

  Rename the positional parameters $N+1,$N+2 ... to , ...  If N is

shell 扩展由 shell 执行,甚至在您的脚本被调用之前。这意味着您必须 quote/escape 参数。在脚本中,可以使用eval进行扩容。

#!/bin/bash
arg1="" ; shift
arg2="" ; shift
eval "list=($@)"
for q in "${list[@]}" ; do echo "$q" ; done

$ ./a 123 456 'a{b,c}' 'd*'
ab ac d.pl docs

我看不出在您的示例中在脚本内部进行扩展有什么意义。

#!/bin/bash
arg1="" ; shift
arg2="" ; shift
list=("$@")
for q in "${list[@]}" ; do echo "$q" ; done

或者只是

#!/bin/bash
arg1="" ; shift
arg2="" ; shift
for q in "$@" ; do echo "$q" ; done

$ ./a 123 456 a{b,c} d*
ab
ac
d.pl
docs