как проверить пустой ли каталог

Вы можете преобразовать файлы , закодированные в EBCDIC, в ASCII и наоборот (используя iconv или dd ), но сделав локаль , который использует EBCDIC, потребует большего, чем внесение нескольких изменений в записи таблицы.

Это потому, что в таблицах языковых стандартов указываются только коды символов, которые можно распечатать, какие элементы управления и т. Д. EBCDIC использует другой порядок кодов, так что цифры в EBCDIC - это разные коды в ASCII, буквенные символы находятся в разных местах и ​​т. д. Чтобы существующие программы, использующие ASCII, взаимодействовали с системой, которая считывает / записывает EBCDIC, потребовалось бы двустороннее преобразование между двумя кодировками.

В принципе, такая программа, как luit , может быть расширена для выполнения этого сопоставления. (Сейчас этого не происходит). Даже если были добавлены соответствующие таблицы, возникает дополнительная проблема, заключающаяся в том, что будут работать только простые программы командной строки: вы не сможете запустить vi .

Дополнительная литература:

12
11.05.2015, 10:44
2 ответа

Мой tldr ответ:

function emptydir {
 [ "$1/"* "" = "" ]  2> /dev/null &&
 [ "$1/"..?* "" = "" ]  2> /dev/null &&
 [ "$1/".[^.]* "" = "" ]  2> /dev/null ||
 [ "$1/"* = "$1/*" ]  2> /dev/null && [ ! -e "$1/*" ] &&
 [ "$1/".[^.]* = "$1/.[^.]*" ]  2> /dev/null && [ ! -e "$1/.[^.]*" ] &&
 [ "$1/"..?* = "$1/..?*" ]  2> /dev/null && [ ! -e "$1/..?*" ]
}

Оно совместимо с POSIX и, хотя это не имеет большого значения, обычно работает быстрее, чем решение, которое выводит список каталогов и направляет вывод в grep.

Использование:

if emptydir adir
then
  echo "nothing found" 
else 
  echo "not empty" 
fi

Мне нравится ответ https://unix.stackexchange.com/a/202276/160204, который я перепишу как:

function emptydir {
  ! { ls -1qA "./$1/" | grep -q. ; }
}

Он выводит список каталогов и передает результат в grep. Вместо этого я предлагаю простую функцию, основанную на расширении и сравнении глобусов.

function emptydir {   
 [ "$(shopt -s nullglob; echo "$1"/{,.[^.],..?}*)" = "" ]
}

Эта функция не является стандартной POSIX и вызывает подоболочку с $(). Сначала я объясню эту простую функцию, чтобы мы могли лучше понять окончательное решение (, см. ответ tldr выше )позже.

Пояснение:

Левая сторона (LHS )пуста, если не происходит расширения, что имеет место в случае, когда каталог пуст. Параметр nullglob обязателен, потому что в противном случае, когда совпадений нет, сам глобус является результатом расширения.(Совпадение RHS с глобусами LHS, когда каталог пуст, не работает из-за ложных срабатываний, возникающих, когда глобус LHS соответствует одному файлу с именем самого глобуса :*в глобусе совпадает подстрока *в имени файла. )Выражение в скобках {,.[^.],..?}охватывает скрытые файлы, но не ..или ..

Поскольку shopt -s nullglobвыполняется внутри$()(подоболочки ), она не изменяет параметр nullglobтекущей оболочки, что обычно хорошо. С другой стороны, рекомендуется установить эту опцию в сценариях, потому что это может привести к ошибкам, когда glob возвращает что-то, когда нет совпадения. Таким образом, можно было бы установить опцию nullglob в начале скрипта, и она не понадобится в функции. Имейте это в виду :нам нужно решение, которое работает с опцией nullglob.

Предостережения:

Если у нас нет доступа для чтения к каталогу, функция сообщает так же, как если бы каталог был пуст. Это также относится к функции, которая выводит список каталогов и выдает grep.

Команда shopt -s nullglobне является стандартной POSIX.

Он использует подоболочку, созданную $(). Это не имеет большого значения, но хорошо, если мы сможем этого избежать.

Про:

Не то, чтобы это имело большое значение, но эта функция в четыре раза быстрее предыдущей, если судить по количеству процессорного времени, затрачиваемого ядром внутри процесса.

Другие решения:

Мы можем удалить несовместимую с POSIX команду shopt -s nullglobв левой части и поместить строку "$1/* $1/.[^.]* $1/..?*"в правую и отдельно устранить ложные срабатывания, возникающие, когда у нас есть только файлы с именами '*', .[^.]*или ..?*. ] в каталоге:

function emptydir {
 [ "$(echo "$1"/{,.[^.],..?}*)" = "$1/* $1/.[^.]* $1/..?*" ] &&
 [ ! -e "$1/*" ] && [ ! -e "$1/.[^.]*" ] && [ ! -e "$1/..?*" ]
}

Без команды shopt -s nullglobтеперь имеет смысл удалить подоболочку, но мы должны быть осторожны, потому что мы хотим избежать разбиения на слова и при этом разрешить подстановку подстановки в LHS.В частности, цитирование, чтобы избежать разделения слов, не работает, потому что оно также предотвращает расширение глобуса. Наше решение состоит в том, чтобы рассматривать шары отдельно:

function emptydir {
 [ "$1/"* = "$1/*" ] 2> /dev/null && [ ! -e "$1/*" ] &&
 [ "$1/".[^.]* = "$1/.[^.]*" ] 2> /dev/null && [ ! -e "$1/.[^.]*" ] &&
 [ "$1/"..?* = "$1/..?*" ] 2> /dev/null && [ ! -e "$1/..?*" ]
}

У нас по-прежнему есть разделение слов для отдельных глобусов, но теперь это нормально, потому что это приведет к ошибке только в том случае, если каталог не пуст. Мы добавили 2> /dev/null, чтобы сбросить сообщение об ошибке, когда есть много файлов, соответствующих данному глобусу в LHS.

Напомним, что нам нужно решение, которое работает и с опцией nullglob. Приведенное выше решение терпит неудачу с опцией nullglob, потому что, когда каталог пуст, LHS также пуст. К счастью, он никогда не говорит, что каталог пуст, если это не так. Он только не может сказать, что он пуст, когда он есть. Таким образом, мы можем управлять параметром nullglob отдельно. Мы не можем просто добавить случаи [ "$1/"* = "" ]и т. д., потому что они расширятся как [ = "" ]и т. д., которые синтаксически неверны. Итак, вместо этого мы используем [ "$1/"* "" = "" ]и т. д. Мы снова должны рассмотреть три случая *, ..?*и .[^.]*для поиска скрытых файлов, но не .и ... Они не будут мешать, если у нас нет опции nullglob, потому что они также никогда не говорят, что она пуста, если это не так. Итак, окончательное предлагаемое решение:

function emptydir {
 [ "$1/"* "" = "" ]  2> /dev/null &&
 [ "$1/"..?* "" = "" ]  2> /dev/null &&
 [ "$1/".[^.]* "" = "" ]  2> /dev/null ||
 [ "$1/"* = "$1/*" ]  2> /dev/null && [ ! -e "$1/*" ] &&
 [ "$1/".[^.]* = "$1/.[^.]*" ]  2> /dev/null && [ ! -e "$1/.[^.]*" ] &&
 [ "$1/"..?* = "$1/..?*" ]  2> /dev/null && [ ! -e "$1/..?*" ]
}

Вопросы безопасности:

Создайте два файла rmи xв пустом каталоге и выполните *по запросу. Глоб *расширится до rm x, и это будет выполнено для удаления x. Это не проблема безопасности, потому что в нашей функции глобусы расположены там, где расширения рассматриваются не как команды, а как аргументы, как и в for f in *.

2
27.01.2020, 19:54

Вот еще один простой способ сделать это. Предположим, что D — это полное имя каталога, который вы хотите проверить на пустоту.

Тогда

if [[ $( du -s  D |awk ' {print $1}') = 0 ]]
then
      echo D is empty
fi

Это работает, потому что

du -s D

имеет в качестве вывода

size_of_D   D

awk удаляет D, и если размер равен 0, каталог пуст.

1
15.03.2020, 17:03

Теги

Похожие вопросы