我有一个脚本:
#!/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
之外,还有其他方法可以解决这个问题吗?
答案 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[@]}"