Bash脚本 - shell命令输出重定向

6
有人可以帮忙解释一下以下内容吗:
如果我输入:

If I type:

a=`ls -l`

然后,ls命令的输出被保存在变量a中。

但如果我尝试执行:

a=`sh ./somefile`

结果输出到shell (stdout)而不是变量a。我期望的是将shell尝试执行脚本'somefile'的结果操作存储在变量中。

请指出我的理解有什么问题,以及可能的解决方法。

谢谢。

编辑:

澄清一下,脚本'somefile'可能存在,也可能不存在。如果存在,则希望将脚本的输出存储在'a'中。如果不存在,则希望将错误消息“没有这样的文件或目录”存储在'a'中。
3个回答

15
我认为是因为shell可能会附加到/dev/tty上,但我可能错了。为什么不直接在脚本上设置执行权限并使用:
a=`./somefile`

如果你想将stderr和stdout捕获到一个文件中,只需使用以下命令:

a=`./somefile 2>&1`

首先,检查文件是否可执行:

if [[ -x ./somefile ]] ; then
    a=$(./somefile 2>&1)
else
    a="Couldn't find the darned thing."
fi

你会注意到我正在切换到$()方法而不是反引号。我更喜欢$(),因为你可以嵌套它们(例如,"a=$(expr 1 + $(expr 2 + 3))")。


不是关于权限的问题...我想要错误信息或返回值被存储在变量中。 - RomanM
我的意思是你不需要运行sh来运行脚本(如果你这样做,sh会对输出施加自己的防火墙)。直接运行脚本即可,为此,你需要使用“chmod +x”命令。 - paxdiablo
尝试以下命令:"chmod u+x somefile; a=./somefile",然后查看a被设置为什么。 - paxdiablo
但对于我的情况,某个文件可能不存在,如何避免在 shell 中看到“没有这样的文件或目录”消息,而是将其存储在变量中? - RomanM
你要找的是 "if [[ -x ./somefile ]]"。 - paxdiablo

5

你可以尝试使用 $() 而非反引号进行命令替换,这是一种新的改进方式。

a=$(sh ./somefile)

如果仍然无法正常工作,请检查somefile是否实际上是stderr输出。

可能实际上找不到somefile ;) - Bogdan

2

您是正确的,./somefile 的标准输出被存储在变量 a 中。但是,我假设 somefile 输出到 stderr。您可以在 ./somefile 之后直接使用 2>&1 重定向它。


哦,我想我明白了。所以在“somefile”不存在的情况下,存储在a中的输出什么都没有,但是脚本默认重定向到stderr,这就是为什么我在屏幕上看到错误消息而不是存储在变量中的原因? - RomanM
1
不,sh 的标准输出被存储在变量 a 中,而 sh 并没有将 ./somefile 的标准输出传递回其调用者。 - paxdiablo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接