Поиск пустых каталогов UNIX

Мне нужно найти пустые каталоги для данного списка каталогов. В некоторых каталогах есть каталоги внутри.

Если внутренние каталоги также пусты, я могу сказать, что главный каталог пуст, иначе он не будет пустым.

Как я могу проверить это?

Например:

A>A1(file1),A2 this is not empty beacuse of file1
B>B1(no file) this is empty
C>C1,C2 this is empty

Ответ 1

Проверьте, выводит ли find <dir> -type f что-либо. Вот пример:

for dir in A B C; do
    [ -z "'find $dir -type f'" ] && echo "$dir is empty"
done

Ответ 2

Это зависит от того, что вы хотите делать с пустыми каталогами. Я использую следующую команду, когда хочу удалить все пустые каталоги в дереве, например test.

find test -depth -empty -delete

Одно замечание о команде выше: он также удалит пустые файлы, поэтому используйте параметр -type d, чтобы этого не было.

find test -depth -type d -empty -delete

Отбросьте -delete, чтобы просмотреть файлы и каталоги.

Если ваше определение пустого дерева каталогов состоит в том, что оно не содержит файлов, вы сможете вставить что-то вместе в зависимости от того, возвращает ли find test -type f что-либо.

find - отличная утилита, и RTFM рано и часто понимают, как много это можно сделать: -)

Ответ 3

Вы можете использовать следующую команду:

find . -type d -empty

Ответ 4

find directory -mindepth 1 -type d -empty -delete

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

Параметр mindepth предотвращает удаление самого каталога, если он оказался пустым.

Ответ 5

find . -type d -empty

находит и отображает пустые каталоги и подкаталоги в текущем дереве. Например. результирующий список пустых директорий и поддисков:

./2047
./2032
./2049
./2063
./NRCP26LUCcct1/2039
./NRCP26LUCcct1/2054
./NRCP26LUCcct1/2075
./NRCP26LUCcct1/2070

В каталогах не выполняется никаких операций. Они просто перечислены. Это работает для меня.

Ответ 6

Просто найдите пустые dirs

Чтобы просто найти пустые каталоги (как указано в заголовке вопроса), ответ mosg верен:

find -type d -empty

Но -empty может быть недоступен в очень старых версиях find (например, в случае HP-UX), Если это ваш случай, см. Методы, описанные в следующем разделе. Является ли каталог пустым?.

Удалить пустые директории

Это немного сложно: предположим, что каталог MyDir содержит пустые каталоги. После удаления этих пустых каталогов MyDir станет пустой папкой и также будет удалена. Поэтому я использую команду rmdir с опцией --parents (или -p), которая также удаляет родительские каталоги, когда это возможно:

find -type d -empty -exec rmdir -vp --ignore-fail-on-non-empty {} +

В старой версии find оператор + еще не поддерживается, поэтому вместо него можно использовать ;:

find -type d -empty -exec rmdir -vp --ignore-fail-on-non-empty {} `;`

Является ли каталог пустым?

Большинство этих ответов объясняют, как проверить, является ли каталог пустым. Поэтому я предоставляю здесь три различных метода, которые я знаю:

  • [ $(find your/dir -prune -empty) = your/dir ]

    d=your/dir
    if [ x$(find "$d" -prune -empty) = x"$d" ]
    then
      echo "empty (directory or file)"
    else
      echo "contains files (or does not exist)"
    fi
    

    вариация:

    d=your/dir
    if [ x$(find "$d" -prune -empty -type d) = x"$d" ]
    then
      echo "empty directory"
    else
      echo "contains files (or does not exist or is not a directory)"
    fi
    

    Объяснение:

    • find -prune похож на find -maxdepth 0, используя меньше символов
    • find -type d печатает только каталоги
    • find -empty печатает пустые каталоги и файлы

      > mkdir -v empty1 empty2 not_empty
      mkdir: created directory 'empty1'
      mkdir: created directory 'empty2'
      mkdir: created directory 'not_empty'
      > touch not_empty/file
      > find empty1 empty2 not_empty -prune -empty
      empty1
      empty2
      
  • (( ${#files} ))

    Этот трюк составляет 100% bash, но вызывает (порождает) суб-оболочку. Идея состоит из Bruno De Fraine и улучшена комментарием teambob. Я советую это, если вы используете bash и если ваш script не должен быть переносимым.

    files=$(shopt -s nullglob dotglob; echo your/dir/*)
    if (( ${#files} ))
    then 
      echo "contains files"
    else 
      echo "empty (or does not exist or is a file)"
    fi
    

    Примечание. нет разницы между пустым каталогом и несуществующим (и даже если предоставленный путь является файлом).

  • [ $(ls -A your/dir) ]

    Этот трюк вдохновлен статьей nixCraft, опубликованной в 2007 году. Andrew Taylor ответил в 2008 году и gr8can8dian в 2011 году.

    if [ "$(ls -A your/dir)" ]
    then
      echo "contains files"
    else
      echo "empty (or does not exist or is a file)"
    fi
    

    или однострочная версия бахизма:

    [[ "$(ls -A your/dir)" ]] && echo "contains files" || echo "empty or ..."
    

    Примечание. ls возвращает $?=2, когда каталог не существует. Но никакой разницы между файлом и пустым каталогом.

Ответ 7

Эта рекурсивная функция, похоже, выполняет трюк:

# Bash
findempty() {
    find ${1:-.} -mindepth 1 -maxdepth 1 -type d | while read -r dir
    do
        if [[ -z "$(find "$dir" -mindepth 1 -type f)" ]] >/dev/null
        then
            findempty "$dir"
            echo "$dir"
        fi
    done
}

Учитывая эту структуру каталогов примера:

    .
    |-- dir1/
    |-- dir2/
    |   `-- dirB/
    |-- dir3/
    |   `-- dirC/
    |       `-- file5
    |-- dir4/
    |   |-- dirD/
    |   `-- file4
    `-- dir5/
        `-- dirE/
            `-- dir_V/

Результатом выполнения этой функции будет:

    ./dir1
    ./dir5/dirE/dir_V
    ./dir5/dirE
    ./dir5
    ./dir2/dirB
    ./dir2

который пропускает /dir4/dirD. Если вы переместите рекурсивный вызов findempty "$dir" после fi, функция будет включать этот каталог в свои результаты.

Ответ 8

Как насчет rmdir *? Эта команда завершится с ошибкой в ​​непустых каталогах.

Ответ 9

Я создал простую структуру следующим образом:


test/
test/test2/
test/test2/test2.2/
test/test3/
test/test3/file

test/test3/file содержит некоторый нежелательный текст.

Выдача find test -empty возвращает "test/test2/test2.2" как единственный пустой каталог.

Ответ 10

был бы простой подход,

$ [ "$(ls -A /path/to/direcory)" ] && echo "not empty" || echo "its empty"

и

if [ "$(ls -A /path/to/direcory)" ]; then
   echo "its not empty"
else 
   echo "empty directory"

Ответ 11

find . -name -type d -ls |awk '($2==0){print $11}'