Как я могу проверить, выводит ли команда пустую строку?
Проверьте, выводит ли команда пустую строку
Ответ 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 для публикации этой идеи в комментариях ниже)
- или даже лучше - подсчитайте количество максимально 1 символа
- сравните это число с нулем
Так, например, вместо:
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
Ответ 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
Ответ 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.