测试如果一个命令输出空串(Test if a command outputs an empty st

2019-06-17 21:48发布

我怎么能测试一个命令输出空字符串?

Answer 1:

此前,这个问题问到如何检查是否有目录中的文件。 下面的代码实现了,但看到RSP的回答了一个更好的解决方案。


空输出

命令不返回值的-他们输出他们。 您可以通过使用捕获该输出命令替换 ; 如$(ls -A) 您可以测试在猛砸非空字符串是这样的:

if [[ $(ls -A) ]]; then
    echo "there are files"
else
    echo "no files found"
fi

请注意,我用-A而不是-a ,因为它忽略了一个象征性的电流( . )和父( .. )目录项。

注:由于在评论中指出,命令替换不能捕获后换行 。 因此,如果该命令输出换行符替换将捕获任何测试将返回false。 虽然不太可能,这是有可能在上面的例子中,因为一个换行符是一个有效的文件名! 更多相关信息, 这个答案 。


退出代码

如果你想检查命令成功完成,你可以检查$? ,其中包含的最后一个命令的退出代码(零成功,失败非零)。 例如:

files=$(ls -A)
if [[ $? != 0 ]]; then
    echo "Command failed."
elif [[ $files ]]; then
    echo "Files found."
else
    echo "No files found."
fi

更多信息这里 。



Answer 2:

TL; DR

if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then ...; fi

由于netj的建议,以提高我的原文:
if [[ $(ls -A | wc -c) -ne 0 ]]; then ...; fi


这是一个老问题,但我看到的是需要一些改进或至少一些澄清至少两件事情。

第一个问题

我看到的第一个问题是,大部分在这里提供的例子, 只是不工作 。 他们使用ls -alls -Al命令-这两者的输出非空字符串的空目录。 这些例子始终都报告说, 即使有没有文件。

出于这个原因,你应该只使用ls -A -为什么会有人想使用-l开关,这意味着当你想要的是测试如果有任何输出由你,反正“使用长列表格式”?

所以,这里的大部分答案都是简单的不正确。

第二个问题

第二个问题是,虽然一些答案做工精细(那些使用ls -alls -Alls -A代替)他们都做这样的事情:

  1. 运行命令
  2. 缓冲RAM中的整个输出
  3. 输出转换成一个巨大的单行线
  4. 该字符串比较空字符串

我建议做,而不是将是:

  1. 运行命令
  2. 算上其输出的字符,而不将它们存储
    • 甚至更好-数最大为字符的数目using head -c1
      (感谢netj张贴这一想法在下面的评论)
  3. 对比这一数字为零

因此,例如,而不是:

if [[ $(ls -A) ]]

我会用:

if [[ $(ls -A | wc -c) -ne 0 ]]
# or:
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]

代替:

if [ -z "$(ls -lA)" ]

我会用:

if [ $(ls -lA | wc -c) -eq 0 ]
# or:
if [ $(ls -lA | head -c1 | wc -c) -eq 0 ]

等等。

对于小的输出可能不是一个问题,但对于更大的输出的不同可以是显著:

$ time [ -z "$(seq 1 10000000)" ]

real    0m2.703s
user    0m2.485s
sys 0m0.347s

与比较:

$ time [ $(seq 1 10000000 | wc -c) -eq 0 ]

real    0m0.128s
user    0m0.081s
sys 0m0.105s

更妙的是:

$ time [ $(seq 1 10000000 | head -c1 | wc -c) -eq 0 ]

real    0m0.004s
user    0m0.000s
sys 0m0.007s

完整的示例

更新由威尔Vousden答案例如:

if [[ $(ls -A | wc -c) -ne 0 ]]; then
    echo "there are files"
else
    echo "no files found"
fi

通过netj建议后再次更新:

if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then
    echo "there are files"
else
    echo "no files found"
fi

丢弃空白

如果您正在测试可以输出一些空白要当作一个空字符串,然后而不是命令:

| wc -c

你可以使用:

| tr -d ' \n\r\t ' | wc -c

或者用head -c1

| tr -d ' \n\r\t ' | head -c1 | wc -c

或类似的东西。

摘要

  1. 首先,使用效果的命令。

  2. 第二,避免了潜在的巨大数据的RAM和处理不必要的存储。

答案没有指定的输出始终是小,所以需要考虑,以及大输出的可能性。



Answer 3:

if [ -z "$(ls -lA)" ]; then
  echo "no files found"
else
  echo "There are files"
fi

这将运行该命令并检查返回的输出(字符串)是否具有零长度。 你可能要检查的“测试”手册页的其他标志。

使用正在检查“”周围的说法,否则空的结果将导致一个语法错误,因为没有给出第二个参数(检查)!

注意: ls -la总是返回...所以使用这是行不通的,看LS手册页 。 此外,虽然这看起来方便和容易的,我想这将打破容易。 写一个小脚本/应用程序,根据结果返回0或1可靠得多!



Answer 4:

对于那些谁想要一个优雅,bash的版本无关的解决方案(其实应该在其他现代shell工作)和那些谁爱用单行快速任务。 开始了!

ls | grep . && echo 'files found' || echo 'files not found'

(注意:作为一个评论提到, ls -al而事实上,只是-l-a将所有返回的东西,所以我的答案我用简单的ls



Answer 5:

由于乔恩林评论说, ls -al将一直输出(为... )。 你想ls -Al避免这两个目录。

例如,你可以把命令的输出到一个shell变量:

v=$(ls -Al)

一个旧的,非嵌套的,符号是

v=`ls -Al`

但我更喜欢嵌套符号$( ... )

在你可以测试是否该变量非空

if [ -n "$v" ]; then
    echo there are files
else
    echo no files
fi

你可以结合既是if [ -n "$(ls -Al)" ]; then if [ -n "$(ls -Al)" ]; then



Answer 6:

巴什参考手册

6.4 Bash的条件表达式

-z string
     True if the length of string is zero.

-n string
string
     True if the length of string is non-zero.

您可以使用速记版本:

if [[ $(ls -A) ]]; then
  echo "there are files"
else
  echo "no files found"
fi


Answer 7:

我猜你想要的输出ls -al命令,这样在bash,你会碰到这样的:

LS=`ls -la`

if [ -n "$LS" ]; then
  echo "there are files"
else
  echo "no files found"
fi


Answer 8:

这里有一个更极端的情况下的解决方案:

if [ `command | head -c1 | wc -c` -gt 0 ]; then ...; fi

这将工作

  • 所有的Bourne shell;
  • 如果命令输出为全零;
  • 有效地无论输出大小的;

然而,

  • 一旦什么是输出的命令或它的子进程就会被杀死。


Answer 9:

所有的答案给出到目前为止处理终止 ,并输出一个非空字符串命令。

大多数被破坏下面的意义:

  • 他们不使用命令只输出换行符妥善处理;
  • 从Bash≥4.4最开始将垃圾邮件标准错误,如果命令输出空字节(因为它们使用命令取代);
  • 大多数人会发出声音完整输出流,所以会等到命令应答之前终止。 一些命令从未终止(尝试,例如, yes )。

因此,要解决所有这些问题,并有效地回答以下问题,

我怎么能测试一个命令输出空字符串?

您可以使用:

if read -n1 -d '' < <(command_here); then
    echo "Command outputs something"
else
    echo "Command doesn't output anything"
fi

您也可以添加一些超时,以测试命令是否输出给定时间内的非空字符串,用read-t选项。 例如,用于2.5秒超时:

if read -t2.5 -n1 -d '' < <(command_here); then
    echo "Command outputs something"
else
    echo "Command doesn't output anything"
fi

备注。 如果你认为你需要确定一个命令是否输出非空字符串,你很可能有一个XY问题。



Answer 10:

下面是写STD-出来的一些STD-ERR命令一个临时文件,然后检查,看看是否文件是空的另一种方法。 这种方法的好处是,它抓住了两个输出,并且不使用子壳或管道。 后面的这些方面是很重要的,因为他们可以捕捉的bash退出处理干扰(如这里 )

tmpfile=$(mktemp)
some-command  &> "$tmpfile"
if [[ $? != 0 ]]; then
    echo "Command failed"
elif [[ -s "$tmpfile" ]]; then
    echo "Command generated output"
else
    echo "Command has no output"
fi
rm -f "$tmpfile"


Answer 11:

有时你要保存的输出,如果它非空,将它传递给另一个命令。 如果是这样,你可以使用类似

list=`grep -l "MY_DESIRED_STRING" *.log `
if [ $? -eq 0 ]
then
    /bin/rm $list
fi

这样, rm ,如果该列表是空的命令不会挂起。



文章来源: Test if a command outputs an empty string
标签: bash shell