Як я можу перевірити, якщо команда видає порожній рядок?
ifneдля цього. joeyh.name/code/moreutils
Як я можу перевірити, якщо команда видає порожній рядок?
ifneдля цього. joeyh.name/code/moreutils
Відповіді:
Раніше в питанні задавали питання, як перевірити, чи є файли в каталозі. Наступний код цього домагається, але див . Відповідь rsp для кращого рішення.
Команди не повертають значення - вони виводять їх. Ви можете захопити цей вихід, використовуючи підстановку команд ; напр $(ls -A). Ви можете перевірити наявність порожньої рядка в Bash так:
if [[ $(ls -A) ]]; then
echo "there are files"
else
echo "no files found"
fi
Зауважте, що я -Aскоріше використовував -a, оскільки він опускає символьні записи поточного ( .) та батьківського ( ..) каталогу.
Примітка. Як зазначено в коментарях, заміна команд не фіксує останніх рядків . Тому, якщо команда виводить лише нові рядки, заміна нічого не фіксує, і тест поверне помилковим. Хоча це малоймовірно, це можливо у наведеному вище прикладі, оскільки один новий рядок є дійсним іменем файлу! Більше інформації у цій відповіді .
Якщо ви хочете перевірити, що команда успішно виконана, ви можете перевірити $?, що містить вихідний код останньої команди (нуль для успіху, не нуль для відмови). Наприклад:
files=$(ls -A)
if [[ $? != 0 ]]; then
echo "Command failed."
elif [[ $files ]]; then
echo "Files found."
else
echo "No files found."
fi
Більше інформації тут .
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замість цього) всі вони роблять що - щось на зразок цього:
Я б запропонував зробити це замість цього:
using head -c1Так, наприклад, замість:
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
Додаткове оновлення jakeonfire :
grepвийде з відмовою, якщо не буде збігу. Ми можемо скористатися цим, щоб трохи спростити синтаксис:
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
Якщо команда, яку ви тестуєте, може вивести деякий пробіл, який ви хочете розглянути як порожній рядок, то замість:
| wc -c
Ви можете використовувати:
| tr -d ' \n\r\t ' | wc -c
або з head -c1:
| tr -d ' \n\r\t ' | head -c1 | wc -c
чи щось подібне.
Спочатку скористайтеся командою, яка працює .
По-друге, уникайте зайвого зберігання в оперативній пам’яті та обробки потенційно величезних даних.
У відповіді не вказано, що вихід завжди малий, тому потрібно також враховувати можливість великого виходу.
[[ $(... | head -c | wc -c) -gt 0 ]]або [[ -n $(... | head -c1) ]]краще, тому що wc -cповинен був би споживати весь результат команди.
if [ -z "$(ls -lA)" ]; then
echo "no files found"
else
echo "There are files"
fi
Це запустить команду і перевірить, чи має повернутий вихід (рядок) нульову довжину. Ви можете перевірити сторінки "тестування" інструкцій щодо інших прапорів.
Використовуйте аргумент "", який перевіряється, інакше порожні результати призведуть до синтаксичної помилки, оскільки не вказано другого аргументу (для перевірки)!
Примітка: це ls -laзавжди повертається, .і ..тому використання цього не вийде, див . Сторінки з посібниками . Крім того, хоча це може здатися зручним і легким, я вважаю, що це легко зламається. Написання невеликого сценарію / програми, що повертає 0 або 1 залежно від результату, набагато надійніше!
$(замість зворотної цитати, тому що$( гніздо краще
Для тих, хто хоче елегантне, базове рішення, незалежне від версій (адже воно повинно працювати в інших сучасних оболонках), а також тих, хто любить користуватися одноклассниками для швидких завдань. Ось і ми!
ls | grep . && echo 'files found' || echo 'files not found'
(зауважте, як один із згаданих коментарів, ls -alа насправді просто -lі -aвсе щось поверне, тому у своїй відповіді я використовую простеls
grep -q ^замість цього, символи нового рядка також будуть відповідні, і grep нічого не надрукує до стандартного виводу. Крім того, він вийде, як тільки отримає будь-який вхід, а не чекає завершення вхідного потоку.
ls -Aякщо ви хочете включити dot-файли (або каталоги)
-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
stringце просто синонім -n string.
Як прокоментував Джон Лін, 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
Я здогадуюсь, що ви хочете вивести ls -alкоманду, тож у bash ви матимете щось на кшталт:
LS=`ls -la`
if [ -n "$LS" ]; then
echo "there are files"
else
echo "no files found"
fi
lsніколи не виконується. Ви лише перевіряєте, чи розширення змінної LS не порожнє.
-aВимикач ніколи не буде повертати ніякого змісту (тобто, він буде повертати вміст , чи є файли чи ні) , так як завжди є неявна .і ..каталоги присутні.
Ось рішення для більш екстремальних випадків:
if [ `command | head -c1 | wc -c` -gt 0 ]; then ...; fi
Це спрацює
проте,
Усі наведені відповіді дотепер стосуються команд, які завершують та видають не порожній рядок.
Більшість розбивається в таких сенсах:
yes).Отже, щоб виправити всі ці проблеми та ефективно відповісти на наступне питання,
Як я можу перевірити, якщо команда видає порожній рядок?
Ви можете використовувати:
if read -n1 -d '' < <(command_here); then
echo "Command outputs something"
else
echo "Command doesn't output anything"
fi
Ви також можете додати деякий час очікування, щоб перевірити, чи команда виводить непусту рядок протягом заданого часу, використовуючи опцію read's -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.
seq 1 10000000, seq 1 20і printf""). Єдиний збіг цього підходу для читання не виграв - це -z "$(command)"підхід для порожнього введення. Навіть тоді вона втрачається лише приблизно на 10-15%. Вони ніби ламаються навіть навколо seq 1 10. Незважаючи на те, -z "$(command)"підхід стає настільки повільним, що збільшується розмір вводу, що я б уникав використовувати його для будь-якого введення змінного розміру.
Ось альтернативний підхід, який записує std-out та std-err деякої команди тимчасовий файл, а потім перевіряє, чи цей файл порожній. Перевага такого підходу полягає в тому, що він фіксує обидва виходи, і не використовує підкорпуси або труби. Останні аспекти є важливими, оскільки вони можуть перешкоджати захопленню керування виїзними ударами (наприклад, тут )
tmpfile=$(mktemp)
some-command &> "$tmpfile"
if [[ $? != 0 ]]; then
echo "Command failed"
elif [[ -s "$tmpfile" ]]; then
echo "Command generated output"
else
echo "Command has no output"
fi
rm -f "$tmpfile"
Іноді потрібно зберегти висновок, якщо він не порожній, передати його іншій команді. Якщо так, ви можете використовувати щось подібне
list=`grep -l "MY_DESIRED_STRING" *.log `
if [ $? -eq 0 ]
then
/bin/rm $list
fi
Таким чином, rmкоманда не зависне, якщо список порожній.