Проверьте, выводит ли команда пустую строку

Как я могу проверить, выводит ли команда пустую строку?

Ответ 1

Ранее вопрос задавался вопросом, есть ли файлы в каталоге. Следующий код достигает этого, но см. rsp answer для лучшего решения.


Пустой выход

Команды не возвращают значения - они выводят их. Вы можете записать этот вывод с помощью замены команд; например $(ls -A). Вы можете проверить непустую строку в Bash следующим образом:

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

Подробнее здесь.

Ответ 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 -al и ls -al - оба из которых выводят непустые строки в пустые каталоги. В тех примерах всегда сообщается, что есть файлы , даже если их нет.

По этой причине вы должны использовать только ls -A. Почему кто-то хочет использовать переключатель -l, что означает "использовать длинный формат списка", когда все, что вам нужно, это тест, если есть какой-либо вывод или нет?

Таким образом, большинство ответов здесь просто неверны.

Вторая проблема

Вторая проблема заключается в том, что в то время как некоторые ответы работают нормально (те, которые не используют, используют ls -al или ls -al, но ls -A), все они делают что-то вроде этого:

  • запустите команду
  • буферный весь его вывод в оперативной памяти
  • преобразует вывод в огромную однострочную строку
  • сравните эту строку с пустой строкой

Вместо этого я бы предложил:

  • запустите команду
  • подсчитывать символы на своем выходе, не сохраняя их
    • или даже лучше - подсчитайте количество максимально 1 символа using head -c1
      (спасибо netj для публикации этой идеи в комментариях ниже)
  • сравните это число с нулем

Так, например, вместо:

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

Полный пример

Обновленный пример из ответа Уилла Вузента:

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

или что-то в этом роде.

Резюме

  • Сначала используйте команду работает.

  • Во-вторых, избегайте ненужного хранения в ОЗУ и обработки потенциально огромных данных.

В ответе не указывалось, что вывод всегда мал, поэтому необходимо учитывать возможность большого вывода.

Ответ 3

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

Это приведет к выполнению команды и echt, имеет ли возвращаемый вывод (строка) нулевую длину. Вы можете проверить страницы 'test для других флагов.

Используйте "" вокруг аргумента, который проверяется, иначе пустые результаты приведут к синтаксической ошибке, так как нет второго аргумента (чтобы проверить)!

Примечание: ls -la всегда возвращает . и .., поэтому использование этого не будет работать, см. страницы ls manual. Кроме того, хотя это может показаться удобным и легким, я предполагаю, что он легко сломается. Написание небольшого script/приложения, которое возвращает 0 или 1 в зависимости от результата, намного надежнее!

Ответ 4

Для тех, кто хочет элегантное, bash независимое от версии решение (на самом деле должно работать в других современных оболочках) и тех, кто любит использовать однострочники для быстрых задач. Вот так!

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

(обратите внимание на один из упомянутых комментариев, ls -al и на самом деле просто -l и -a все вернут что-то, поэтому в своем ответе я использую простой ls

Ответ 5

Как сказал Джон Лин, ls -al всегда будет выводить (для . и ..). Вы хотите ls -al избежать этих двух каталогов.

Вы можете, например, поместить вывод команды в переменную оболочки:

v=$(ls -Al)

Более старая, не-вложенная, нотация

v=`ls -Al`

но я предпочитаю вложенную нотацию $(... )

Вы можете проверить, не является ли эта переменная непустой

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

И вы можете комбинировать оба как if [ -n "$(ls -Al)" ]; then

Ответ 7

Я предполагаю, что вы хотите вывод команды ls -al, поэтому в bash у вас будет что-то вроде:

LS=`ls -la`

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

Ответ 8

Здесь решение для более экстремальных случаев:

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

Это будет работать

  • для всех оболочек Борна;
  • если вывод команды - все нули;
  • эффективно независимо от размера вывода;

однако,

  • команда или ее подпроцессы будут убиты, как только что-нибудь выйдет.

Ответ 9

У меня есть тот же самый вопрос, но я делаю это с vbscript, поэтому вот моя строка кода, которую мне нужно знать, если она что-то обнаружила:   crt.Screen.Send "cat myfile.txt | grep" L [0-9] * '"и vbcr

Ответ 10

Все ответы, которые даны до сих пор, касаются команд, которые завершают и выводят непустую строку.

Большинство из них разбиты в следующих смыслах:

  • Они неправильно обрабатывают команды, выводящие только строки новой строки;
  • начиная с 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.