How can I test if a command outputs an empty string?
To check if string is empty in Bash, we can make an equality check with the given string and empty string using string equal-to = operator, or use -z string operator to check if the size of given string operand is zero.
PHP empty() Function The empty() function checks whether a variable is empty or not. This function returns false if the variable exists and is not empty, otherwise it returns true. The following values evaluates to empty: 0.
The -n test will check if $output is a non-empty string. If it is, the content of $output will be printed.
Previously, the question asked how to check whether there are files in a directory. The following code achieves that, but see rsp's answer for a better solution.
Commands don’t return values – they output them. You can capture this output by using command substitution; e.g. $(ls -A)
. You can test for a non-empty string in Bash like this:
if [[ $(ls -A) ]]; then echo "there are files" else echo "no files found" fi
Note that I've used -A
rather than -a
, since it omits the symbolic current (.
) and parent (..
) directory entries.
Note: As pointed out in the comments, command substitution doesn't capture trailing newlines. Therefore, if the command outputs only newlines, the substitution will capture nothing and the test will return false. While very unlikely, this is possible in the above example, since a single newline is a valid filename! More information in this answer.
If you want to check that the command completed successfully, you can inspect $?
, which contains the exit code of the last command (zero for success, non-zero for failure). For example:
files=$(ls -A) if [[ $? != 0 ]]; then echo "Command failed." elif [[ $files ]]; then echo "Files found." else echo "No files found." fi
More info here.
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then ...; fi
Thanks to netj for a suggestion to improve my original:if [[ $(ls -A | wc -c) -ne 0 ]]; then ...; fi
This is an old question but I see at least two things that need some improvement or at least some clarification.
First problem I see is that most of the examples provided here simply don't work. They use the ls -al
and ls -Al
commands - both of which output non-empty strings in empty directories. Those examples always report that there are files even when there are none.
For that reason you should use just ls -A
- Why would anyone want to use the -l
switch which means "use a long listing format" when all you want is test if there is any output or not, anyway?
So most of the answers here are simply incorrect.
The second problem is that while some answers work fine (those that don't use ls -al
or ls -Al
but ls -A
instead) they all do something like this:
What I would suggest doing instead would be:
using head -c1
So for example, instead of:
if [[ $(ls -A) ]]
I would use:
if [[ $(ls -A | wc -c) -ne 0 ]] # or: if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]
Instead of:
if [ -z "$(ls -lA)" ]
I would use:
if [ $(ls -lA | wc -c) -eq 0 ] # or: if [ $(ls -lA | head -c1 | wc -c) -eq 0 ]
and so on.
For small outputs it may not be a problem but for larger outputs the difference may be significant:
$ time [ -z "$(seq 1 10000000)" ] real 0m2.703s user 0m2.485s sys 0m0.347s
Compare it with:
$ time [ $(seq 1 10000000 | wc -c) -eq 0 ] real 0m0.128s user 0m0.081s sys 0m0.105s
And even better:
$ time [ $(seq 1 10000000 | head -c1 | wc -c) -eq 0 ] real 0m0.004s user 0m0.000s sys 0m0.007s
Updated example from the answer by Will Vousden:
if [[ $(ls -A | wc -c) -ne 0 ]]; then echo "there are files" else echo "no files found" fi
Updated again after suggestions by netj:
if [[ $(ls -A | head -c1 | wc -c) -ne 0 ]]; then echo "there are files" else echo "no files found" fi
Additional update by jakeonfire:
grep
will exit with a failure if there is no match. We can take advantage of this to simplify the syntax slightly:
if ls -A | head -c1 | grep -E '.'; then echo "there are files" fi if ! ls -A | head -c1 | grep -E '.'; then echo "no files found" fi
If the command that you're testing could output some whitespace that you want to treat as an empty string, then instead of:
| wc -c
you could use:
| tr -d ' \n\r\t ' | wc -c
or with head -c1
:
| tr -d ' \n\r\t ' | head -c1 | wc -c
or something like that.
First, use a command that works.
Second, avoid unnecessary storing in RAM and processing of potentially huge data.
The answer didn't specify that the output is always small so a possibility of large output needs to be considered as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With