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

时间:2015-02-02 14:52:41

标签: linux bash shell variable-expansion brace-expansion

使用$@,您可以对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=$1
arg2=$2
list=$(find $3)
for file in $list; do _commands_; done
...

主叫:

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

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

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

arg1="$1"
arg2="$2"
shift 2

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

但出于好奇,是否仍然可以在脚本内部将字符串dir1/{subdir1/*.dat,subdir2/*}传递给find命令(或者指向同一端的任何方法),而不使用$@,并获得那种方式的清单?这可能是有用的,例如如果最好让列表不是第一个或最后一个参数,或者在某些其他情况下,即使它需要转义字符或引用参数。

2 个答案:

答案 0 :(得分:4)

您可以在脚本中使用此代码:

arg1="$1"
arg2="$2"
shift 2

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

然后将其称为:

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

使用shift 2会将位置参数移动2个位置,从而将$3设为$1,将$4设为$2等。然后您可以直接调用{{1}迭代其余的参数。

根据$@

help shift

答案 1 :(得分:0)

在您调用脚本之前,shell将执行shell扩展。这意味着您必须引用/转义参数。在脚本中,您可以使用eval执行扩展。

#!/bin/bash
arg1="$1" ; shift
arg2="$2" ; 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="$1" ; shift
arg2="$2" ; shift
list=("$@")
for q in "${list[@]}" ; do echo "$q" ; done

或只是

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

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