4

I am using solutions from Test if a command outputs an empty string. In addition to those solutions, I want to print command's output if its not empty.

I was wondering would it be possible to print command's output if its not empty by calling the command only one time.

I can do it by re-calling the same command inside the if condition, but now second call may consume additional CPU usage, since we already obtained its result.


Possible approach could be, where the same command is called two times:

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

output=$(git diff --ignore-blank-lines --color-words HEAD | tr -d ' \n\r\t ' | wc -c)
if [ "$output" -gt 0 ]; then
    git diff --ignore-blank-lines --color-words HEAD 
else
    echo "diff is empty"
fi
AdminBee
  • 22,803
alper
  • 469
  • 3
    Note that for the specific case of checking the number of names in a directory, ls is not the best tool for the job. It would be better to set -- * (possibly setting nullglob and/or dotglob in bash first) and then look at "$#". – Kusalananda Jul 05 '21 at 14:56
  • For the purpose of the question I can remove ls section, since it leads another question as https://unix.stackexchange.com/questions/657078/how-to-redirect-ls-output-into-less-r-if-the-output-size-is-large

    // For @Stephen Kitt's answer than should we first set set -- * ?

    – alper Jul 05 '21 at 15:03
  • shopt -s nullglob dotglob; set -- *; [ "$#" -eq 0 ] && echo 'no files' – Kusalananda Jul 05 '21 at 15:44
  • Where can I download shopt? // E: Unable to locate package shopt // please note that I am using zsh shell – alper Jul 05 '21 at 17:29
  • shopt is a builtin utility in the bash shell. You tagged your question with the [tag:bash] tag. – Kusalananda Jul 05 '21 at 18:22
  • 1
    Note that this question would have had a totally different set of answers, had you mentioned that you used the zsh shell. – Kusalananda Jul 05 '21 at 18:24
  • 1
    @alper, you're using Zsh, but your question is tagged with [tag:bash] in particular and not [tag:zsh]? – ilkkachu Jul 05 '21 at 19:43
  • 1
    Technically, the answer to the question in the title, to "check if output is non-empty, and print it if it is", is to just print it unconditionally. Since printing an empty output doesn't do anything. But that's not exactly what you want. – ilkkachu Jul 05 '21 at 19:45
  • @ilkkachu I tagged bash by mistake by taking tags from the linked related question, and when I realize my mistake it was too late to change it. I am sorry for this. // In general I was redirecting ls or git diff results into less -R. I just wanted to ignore redirecting into less -R if the command's output is empty and do nothing – alper Jul 05 '21 at 20:01
  • Seems you want git ... | ifne less – muru Jul 06 '21 at 07:41
  • Can we use ifne in zsh shell? @muru – alper Jul 06 '21 at 23:17
  • It's a normal command like any other, so you can use it in any reasonable shell. – muru Jul 07 '21 at 00:16
  • 1
    @alper as two answers there say, it's from the moreutils package. You'll need to install that package. – muru Jul 07 '21 at 09:54

3 Answers3

8

Note: The question was originally tagged , but OP has since stated that the shell used is zsh. This will invalidate the answer somewhat.

You can store the output of a command in a variable and test if that variable is empty:

output="$(your_command)"

if [[ -n $output ]] then printf -- "%s\n" "$output" else printf -- "No output\n" fi

The -n test will check if $output is a non-empty string. If it is, the content of $output will be printed. Otherwise, a message that no output was produced will be printed. Notice that the quotes around the "$output" are necessary.

Notice also that (as mentioned by @ilkkachu), trailing newlines will be removed by the command substitution, so if you care about these, a different approach is necessary.

AdminBee
  • 22,803
3

If you want the output in any case, you can pipe it to tee and use that to duplicate the output without running the command again: once to standard output, once to a command which can act on empty input.

For example:

ls | tee >([ $(wc -m) -gt 0 ] || echo No output)

Note that this only takes care of standard output, so you can end up with “No output” after an error message. You’ll also have to adjust commands accordingly when their output varies depending on whether it’s going to a terminal or not (e.g. ls -C, or output with colours).

ilkkachu
  • 138,973
Stephen Kitt
  • 434,908
  • If the folder is empty it prints ls's output and No output right after it. Is it normal? – alper Jul 05 '21 at 19:01
  • 1
    What output do you get from ls when the folder is empty? It shouldn’t output anything, and then the above adds “No output” as a result... – Stephen Kitt Jul 05 '21 at 20:52
  • Got it. I was trying ls | tee >([ $(wc -m) -gt 100 ] || echo some_output) on non-empty folder hoping to get on some_output output. But as I understand, if the folder is not empty, it will always print the ls output – alper Jul 05 '21 at 22:44
  • Yes, this is an answer to your stated question, “Test if a command's output is an empty string”. Solving your other question about piping output to less if it’s too long is a different matter. – Stephen Kitt Jul 06 '21 at 08:39
1

Taking ls -A as command example, the following will do:

if ls -A | grep ^; then
   : the output was already written
else
   : no output
fi

if ! ls -A | grep ^; then : handle the no-output condition fi

This will also ensure that trailing newlines are preserved in the output.

For the actual case mentioned in this comment (do not run less with an empty output), there's the -F ("quit if one screen") option:

command ... | less -FXR

(you can omit the X with newer versions of less).

AdminBee
  • 22,803