1

我有一个脚本:

#!/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吗?

4

3 回答 3

3

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

正如您正确发现的那样,您需要让外壳程序“再次运行该行”并重新评估您在那里找到的任何变量。

因此,除了 eval 之外别无他法(好吧,您可以使用 subshel​​l 的东西并浪费大量的处理能力,并从本质上用您自己的代码重新制作 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
于 2011-10-13T15:45:12.127 回答
2

似乎是大括号在这里使事情变得混乱。IMO,这种不一致是 shell 中的一个错误——如果你有MULTIPLE_FILES=/tmp/dir1/*.file,它会立即扩展它。添加大括号,然后它停止尝试扩展。当您运行其他任何东西时,情况会有所不同。

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

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

于 2011-10-13T15:53:49.130 回答
1

你可以使用一个数组:

SINGLE_FILE=/tmp/blah.file
MULTIPLE_FILES=( /tmp/{dir1,dir2}/*.file )
cp -t /tmp/newDir "$SINGLE_FILE" "${MULTIPLE_FILES[@]}"
于 2011-10-13T18:45:20.167 回答