Bash脚本参数扩展

时间:2011-10-13 15:31:13

标签: bash eval variable-expansion

我有一个脚本:

#!/bin/bash
SINGLE_FILE=/tmp/blah.file
MULTIPLE_FILES=/tmp/{dir1,dir2}/*.file

cp $SINGLE_FILE $MULTIPLE_FILES /tmp/newDir

这将失败:

  

cp:无法统计`/tmp/{dir1,dir2}/*.file':没有这样的文件或目录

看起来脚本没有扩展变量中的通配符。所以我可以使用这个脚本:

eval cp $SINGLE_FILE $MULTIPLE_FILES /tmp/newDir

我的问题是:为什么脚本首先不扩展我的变量?另外,除了使用eval之外,还有其他方法可以解决这个问题吗?

3 个答案:

答案 0 :(得分:3)

脚本 将您的变量扩展为您设置的值,即/tmp/{dir1,dir2}/*.file,对吗?

正如你正确发现的那样,你需要让shell'再次通过那条线'并重新评估你在那里发现的任何变量。

所以,除了eval之外别无其他方式(好吧你可以填充东西并浪费大量处理能力,并且基本上用自己的代码重新制作eval的功能。)

我唯一可以推荐的是使用shell调试功能set -vx来亲自了解它是如何工作的,即

$set -vx
set -vx
>set -vx
$SINGLE_FILE=/tmp/blah.file
SINGLE_FILE=/tmp/blah.file
>SINGLE_FILE=/tmp/blah.file

$MULTIPLE_FILES=/tmp/{dir1,dir2}/*.file
MULTIPLE_FILES=/tmp/{dir1,dir2}/*.file
>MULTIPLE_FILES='/tmp/{dir1,dir2}/*.file'

$echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir
echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir
>echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir
/tmp/blah.file /tmp/{dir1,dir2}/*.file /tmp/newDir

$eval echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir
eval echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir
>eval echo /tmp/blah.file '/tmp/{dir1,dir2}/*.file' /tmp/newDir
echo /tmp/blah.file /tmp/{dir1,dir2}/*.file /tmp/newDir
>echo /tmp/blah.file '/tmp/dir1/*.file' '/tmp/dir2/*.file' /tmp/newDir
/tmp/blah.file /tmp/dir1/*.file /tmp/dir2/*.file /tmp/newDir

答案 1 :(得分:2)

这似乎是令人困惑的事情。 IMO,这种不一致是shell中的一个错误 - 如果你有MULTIPLE_FILES=/tmp/dir1/*.file,它会立即扩展。添加大括号,然后停止尝试展开。当你在运行任何其他东西时,这是不同的。

与此同时,eval在这里并不是一个糟糕的解决方案/解决方法。我唯一能想到的另一个是MULTIPLE_FILES=$(echo /tmp/{dir1,dir2}/*.file),这不一定更好。

一般来说,我试图避免这种类型的事情,因为当空间在文件/目录名称中时,正确的shell解析很难。相反,我尝试尽可能多地使用find ... -print0 | xargs -0 ...。或直接使用另一种脚本语言,如perl。

答案 2 :(得分:1)

您可以使用数组:

SINGLE_FILE=/tmp/blah.file
MULTIPLE_FILES=( /tmp/{dir1,dir2}/*.file )
cp -t /tmp/newDir "$SINGLE_FILE" "${MULTIPLE_FILES[@]}"