Как из сценария оболочки проверить, есть ли в каталоге файлы?
Что-то похожее на это
if [ -e /some/dir/* ]; then echo "huzzah"; fi;
но это работает, если каталог содержит один или несколько файлов (указанный выше работает только с 0 или 1 файлом).
Ответы:
Решения, которые до сих пор используют
ls
. Вот решение для всех bash:источник
shopt -q nullglob || resetnullglob=1; shopt -s nullglob; shopt -q dotglob || resetdotglob=1; shopt -s dotglob; files=(/some/dir/*); [ "$files" ] && echo "wowzers"; [ "$resetdotglob" ] && shopt -u dotglob; [ "$resetnullglob" ] && shopt -u nullglob;
files=$(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*)
files=$(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*)
тогда оператор if должен измениться наif [ ${#files} -gt 0 ];
или, может быть, вы просто забыли () вокруг команды вспомогательной оболочки?files=($(shopt -s nullglob;shopt -s dotglob;echo /some/dir/*))
Три лучших трюка
shopt -s nullglob dotglob; f=your/dir/*; ((${#f}))
Этот трюк 100%
bash
и вызывает (порождает) суб-оболочку. Идея принадлежит Bruno De Fraine и улучшена комментарием teambob .Примечание: нет разницы между пустым каталогом и несуществующим (даже если указанный путь является файлом).
В «официальном» FAQ для IRC-канала #bash есть похожая альтернатива и более подробная информация (и другие примеры) :
[ -n "$(ls -A your/dir)" ]
Этот трюк основан на статье nixCraft, опубликованной в 2007 году. Добавьте,
2>/dev/null
чтобы подавить ошибку вывода"No such file or directory"
.См. Также ответ Эндрю Тейлора (2008 г.) и ответ gr8can8dian (2011 г.).
или однострочная версия башизма:
Примечание:
ls
возвращается,$?=2
когда каталог не существует. Но никакой разницы между файлом и пустым каталогом.[ -n "$(find your/dir -prune -empty)" ]
Этот последний трюк основан на ответе gravstar, где
-maxdepth 0
он заменен-prune
и улучшен комментарием phils .вариант с использованием
-type d
:Объяснение:
find -prune
похож на чемfind -maxdepth 0
использованию меньшего количества символовfind -empty
печатает пустые каталоги и файлыfind -type d
печатает только каталогиПримечание: вы также можете заменить
[ -n "$(find your/dir -prune -empty)" ]
только сокращенной версией ниже:Этот последний код работает в большинстве случаев, но имейте в виду, что вредоносные пути могут выражать команду ...
источник
[ -n "$(find "your/dir" -prune -empty)" ]
, чтобы избежать повторения пути к каталогу.if [ ``ls -A your/dir`` ]
в сценарии я пришел к выводу, что он отлично работает для каталога с 0, 1 или 2 подкаталогами, но не работает для каталога с более чем 2 подкаталогами.line 17: [: 20150424-002813: unary operator expected
где20150424-002813
было одно из имен каталогов. Используемый снаряд был/bin/bash/
. Я наконец поменял его наls "$destination" | tail -1
if [ ``ls -A my/dir`` ]
выходит по ошибкеbash: [: -A: binary operator expected
. Проверено на bash версий 4.1.2 и 4.2.53.-n
вариант был в заголовке, а затем не в нижеследующем абзаце). Так что да, все в порядке.ls: cannot access '/path': No such file or directory
. Есть ли способ подавить это сообщение? Я бы хотел там молча потерпеть неудачу.Как насчет следующего:
Таким образом, нет необходимости создавать полный список содержимого каталога. Это
read
одновременно и отбрасывает вывод, и делает выражение истинным только тогда, когда что-то читается (т./some/dir/
Е. Обнаруживается пустымfind
).источник
find /some/dir/ -maxdepth 0 -empty -exec echo "huzzah" \;
ls
вывода и не полагается на функции оболочки, отличные от стандартных.-maxdepth
и-empty
первичные цвета.Пытаться:
источник
/bin/ls <some_dir>/* 2> /dev/null
if [! -z "$ tmp"]; then echo Something is there fils /some/dir/*
]; затем эхо "ура"; fi-n
вместо! -z
(они оба эквивалентны, но почему бы не использовать более короткую форму, если она существует).BigGray% if [ ! -z
ls / some / dir / * `]; затем эхо "ура"; fi zsh: совпадений не найдено: / some / dir / * `ls...
в bashисточник
Позаботьтесь о каталогах с большим количеством файлов! Чтобы оценить
ls
.ИМО лучшее решение - это то, которое использует
источник
источник
Не могли бы вы сравнить результат этого?
источник
Некоторые примечания по реализации:
for
Цикл избегает вызов внешнегоls
процесса. Он по-прежнему считывает все записи каталога один раз. Это можно оптимизировать, только написав программу на C, которая явно использует readdir ().test -e
Внутри цикла ловит случай пустой каталог, в этом случае переменная_ief
будет присвоено значение «somedir / *». Только если этот файл существует, функция вернет "непустой"test
реализация не поддерживает-e
флаг.источник
dotglob
не установлено -shopt -s dotglob
Это говорит мне, пуст ли каталог или нет, количество файлов, которые он содержит.
источник
ls
.Это может быть очень поздний ответ, но вот решение, которое работает. Эта строка распознает только наличие файлов! Это не даст вам ложного срабатывания, если каталоги существуют.
источник
Предположим , у вас нет файла с именем
*
в/any/dir/you/check
, он должен работать наbash
dash
posh
busybox sh
иzsh
а (для Zsh) требуетсяunsetopt nomatch
.Характеристики должны быть сопоставимы с теми,
ls
которые используют*
(glob), я думаю, будет медленным в каталогах с большим количеством узлов (мой/usr/bin
с более чем 3000 файлами пошел не так медленно), будет использовать по крайней мере достаточно памяти, чтобы выделить все каталоги / имена файлов (и многое другое) поскольку все они передаются (разрешаются) в функцию в качестве аргументов, некоторые оболочки, вероятно, имеют ограничения на количество аргументов и / или длину аргументов.Было бы неплохо иметь переносимый быстрый способ с нулевыми ресурсами O (1), чтобы проверить, пуст ли каталог.
Обновить
Версия выше , не учитывает скрытые файлы / директории, в случае , если требуются еще несколько испытаний, как
is_empty
от ш Рича (POSIX оболочки) уловки :Но вместо этого я думаю о чем-то вроде этого:
Некоторая озабоченность по поводу отличий конечных косых черт от аргумента и вывода find, когда каталог пуст, и конечных символов новой строки (но с этим должно быть легко справиться), к сожалению, на моем
busybox
sh
шоу, что, вероятно, является ошибкой наfind -> dd
конвейере с выводом, усеченным случайным образом ( если я использовал,cat
то вывод всегда один и тот же, вроде быdd
с аргументомcount
).источник
is_empty(){ [ ! -d "${1}" ] && return 2;set -- "${1}" "${1}"/* "${1}"/.[!.]* "${1}"/..?*;[ "${*}" = "${1} ${1}/* ${1}/.[!.]* ${1}/..?*" ]; };
ЗШ
Я знаю, что вопрос был помечен как bash; но, для справки, для пользователей zsh :
Проверить наличие непустого каталога
Чтобы проверить,
foo
не пусто ли:где, если
foo
не пусто, будет выполнен код вfor
блоке.Проверить наличие пустого каталога
Чтобы проверить,
foo
пусто ли:где, если
foo
пусто, будет выполнен код вfor
блоке.Ноты
Нам не нужно было цитировать каталог
foo
выше, но мы можем сделать это, если нам нужно:Мы также можем протестировать более одного объекта, даже если это не каталог:
Все, что не является каталогом, просто игнорируется.
Дополнительно
Поскольку мы используем глобус, мы можем использовать любой глобус (или расширение скобок):
Мы также можем исследовать объекты, помещенные в массив. С каталогами, как указано выше, например:
Таким образом, мы можем тестировать объекты, которые, возможно, уже были установлены в параметре массива.
Обратите внимание, что код в
for
блоке, очевидно, выполняется по очереди в каждом каталоге. Если это нежелательно, вы можете просто заполнить параметр массива, а затем работать с этим параметром:объяснение
Для пользователей zsh существует
(F)
квалификатор glob (см.man zshexpn
), Который соответствует "полным" (непустым) каталогам:Квалификатор
(F)
перечисляет объекты, которые соответствуют: - это каталог И не является пустым. Итак,(^F)
совпадения: не каталог ИЛИ пуст. Таким образом, в(^F)
одиночку также будут перечислены, например, обычные файлы. Таким образом, как объясняется наzshexp
странице руководства , нам также нужен(/)
квалификатор glob, который перечисляет только каталоги:Таким образом, чтобы проверить, пуст ли данный каталог, вы можете запустить:
и просто чтобы убедиться, что непустой каталог не будет захвачен:
К сожалению! Поскольку
Y
не пусто, zsh не находит совпадений для(/^F)
(«пустые каталоги») и, таким образом, выдает сообщение об ошибке, говорящее, что совпадений для глобуса не найдено. Поэтому нам необходимо подавить эти возможные сообщения об ошибках с помощью(N)
квалификатора glob:Таким образом, для пустых каталогов нам нужен квалификатор
(N/^F)
, который можно читать как «не предупреждать меня о сбоях, каталогах, которые не заполнены».Точно так же для непустых каталогов нам нужен квалификатор
(NF)
, который мы можем также читать как: «не предупреждать меня о сбоях, полные каталоги».источник
Я удивлен, что руководство wooledge по пустым каталогам не упомянуто. Это руководство, как и вся информация о wooledge, является обязательным к прочтению при ответе на вопросы о типах оболочки.
Примечания с этой страницы:
источник
Небольшой вариант ответа Бруно :
Меня устраивает
источник
Взяв подсказку (или несколько) из ответа olibre, мне нравится функция Bash:
Потому что, хотя он создает одну подоболочку, он настолько близок к решению O (1), насколько я могу себе представить, а присвоение ему имени делает его читабельным. Тогда я могу написать
Что касается O (1), то здесь есть исключения: если из большого каталога были удалены все или все, кроме последней записи, «find», возможно, придется прочитать все это целиком, чтобы определить, пуст ли он. Я считаю, что ожидаемая производительность - O (1), но в худшем случае она линейна по размеру каталога. Я этого не измерял.
источник
До сих пор я не видел ответа с использованием grep, который, я думаю, дал бы более простой ответ (не слишком много странных символов!). Вот как я могу проверить, существуют ли какие-либо файлы в каталоге, используя оболочку bourne:
это возвращает количество файлов в каталоге:
вы можете указать путь к каталогу, в который записан каталог. Первая половина вертикальной черты гарантирует, что первым символом вывода будет «-» для каждого файла. Затем egrep подсчитывает количество строк, начинающихся с этого символа, используя регулярные выражения. теперь все, что вам нужно сделать, это сохранить полученное число и сравнить его, используя обратные кавычки, например:
x - это переменная по вашему выбору.
источник
Смешивая чернослив и последние ответы, я должен
это работает и для путей с пробелами
источник
Простой ответ с помощью bash :
источник
Я бы пошел на
find
:Это проверяет результат поиска только файлов в каталоге, не просматривая подкаталоги. Затем он проверяет вывод, используя
-z
параметр, взятый изman test
:Посмотрите некоторые результаты:
Пустой каталог:
Просто в нем режиссеры:
Файл в каталоге:
Файл в подкаталоге:
источник
С помощью некоторого обходного пути я мог найти простой способ узнать, есть ли файлы в каталоге. Это может быть расширено с помощью команд grep для проверки конкретных файлов .xml или .txt и т. Д. Пример:
ls /some/dir | grep xml | wc -l | grep -w "0"
источник
источник
nullglob
, потому что тогдаls
команда будет успешной.для тестирования определенного целевого каталога
источник
Попробуйте с помощью команды find. Укажите каталог жестко или в качестве аргумента. Затем запустите find для поиска всех файлов внутри каталога. Проверьте, является ли возвращение find нулевым. Эхо данных находки
источник
Мне не нравится
ls - A
решения. Скорее всего, вы хотите проверить, пуст ли каталог, потому что вы не хотите его удалять. Следующее делает это. Однако, если вы просто хотите зарегистрировать пустой файл, конечно, его удаление и воссоздание будет быстрее, чем перечисление, возможно, бесконечных файлов?Это должно работать ...
источник
${target}/..
.Для меня это хорошо работает (когда существует каталог):
При полной проверке:
источник