9

如何有效地检查任意命令是否在 POSIX shell 中产生任何输出?(比方说git ls-files --killed。)

有三种明显的方式,但在我看来,每一种都丑陋或邪恶:

  1. [ -n "$(git ls-files --killed)" ] - 命令的完整输出必须在内存中捕获并传递给测试(至少希望是内置的)
  2. [ "$(git ls-files --killed | wc -c)" -gt 0 ] - 涉及两个 fork- exec
  3. TMP=$(临时文件); git ls-files --killed >"$tempfile"; [ -s "$tempfile" ] && ...; rm "$tempfile" - 需要一个中间临时文件(同样也捕获所有输出)
4

4 回答 4

4

您还可以检查命令的退出状态。通常,如果成功运行命令,则返回退出状态 0。

git ls-files --killed > /dev/null
if [ $? -eq 0 ]

或者,如果您只想依赖命令的输出,则可以将“ head -1”与第一个选项一起使用,因为无论如何,除了知道结果之外,您似乎没有对命令输出进行任何处理。

于 2013-06-28T00:29:12.180 回答
4

我首选的解决方案使用 POSIX shell 内置read

if git ls-files --killed | read REPLY; then
  echo "Some output"
else
  echo "No output or git failed"
fi

read尝试从 stdin 读取一行(并读入变量REPLY),如果成功则返回 0,如果失败则返回正的退出代码。管道的其余部分不被读取。仅在 bash中,REPLY如果省略,则为默认名称,因此read REPLY可以缩短为read.

这种方法的一个潜在缺点是未检查相关程序的退出代码(在您的示例中为 git)。

于 2015-08-27T02:16:28.880 回答
1

你可能认为这个解决方案和其他解决方案一样老套,但我认为它使用的内存比其他解决方案少(我不是 shell 脚本效率方面的专家)。

代码仅是 bash:

z=0
while read -r -n1 char; do
  z=1
  break
done < <(git ls-files --killed)
[ $z != 0 ]

它使用临时变量而不是临时文件,我认为 read 一次只能工作一个字符,但 git ls-files 命令可能仍会完全执行。

它可能不会那么丑陋,但我认为它可能至少更有效率。

于 2013-06-28T00:45:29.977 回答
0

因为您提到了 POSIX,所以我将向您推荐我将使用 /usr/bin/test 的这个答案
,因为它是 POSIX 系统所必需的。

/usr/bin/test -n "$(git ls-files --killed)"

于 2013-06-28T00:52:46.653 回答