How to check if the output of a command is nonempty in a POSIX shell?

How to effectively check if an arbitrary command produced any output in the POSIX shell? (Say git ls-files --killed .)

There are three obvious ways, but each seems ugly or evil to me:

  • [-n "$ (git ls-files --killed)"] - the full output of the command should be captured in memory and passed to the test (which I hope, no less, built-in)
  • ["$ (git ls-files --killed | wc -c)" -gt 0] - two fork-execs are involved
  • TMP = $ (temporary files); git ls-files --killed> "$ tempfile"; [-s "$ tempfile"] && & & ...; rm "$ tempfile" - an intermediate temporary file is required (again capturing all output)
+6
source share
4 answers

You can also check the exit status of the team. Typically, commands, if executed successfully, return an exit status of 0.

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

OR, if you only want to depend on the output of the command, you can use " head -1 " along with the 1st option, since in any case it seems to you that you are not doing any processing with the output of the command without knowing the result.

+4
source

My favorite solution uses the built-in POSIX read shell

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

read tries to read a string from stdin (and into the REPLY variable) and returns 0 if successful, or a positive exit code if it fails. The rest of the pipeline is not readable. Only in bash REPLY is the default name if omitted, so read REPLY can be shortened to read .

A potential drawback of this approach is that the exit code of the program in question (git in your example) is not checked.

+3
source

You might think that this solution is just as hacky as the others, but I think it uses less memory than others (I am not an expert on the effectiveness of the shell script).

Bash code:

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

It uses a temporary variable instead of a temporary file, and I think that reading only works with one char at a time, but the git ls-files command can be fully executed.

It may not be much less ugly, but I think it can be at least more efficient.

+1
source

Since you mention POSIX, I will give you this answer
I would use / usr / bin / test because it is required for POSIX systems.

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

-1
source

Source: https://habr.com/ru/post/948285/


All Articles