Поиск пустых каталогов UNIX - PullRequest
87 голосов
/ 11 мая 2010

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

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

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

Например:

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

Ответы [ 11 ]

240 голосов
/ 11 мая 2010

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

find test -depth -empty -delete

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

find test -depth -type d -empty -delete

Удалите -delete, чтобы увидеть совпадение файлов и каталогов.

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

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

37 голосов
/ 11 мая 2010

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

find . -type d -empty
33 голосов
/ 11 мая 2010

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

for dir in A B C; do
    [ -z "`find $dir -type f`" ] && echo "$dir is empty"
done
25 голосов
/ 13 июня 2011
find directory -mindepth 1 -type d -empty -delete

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

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

21 голосов
/ 24 февраля 2017

find . -type d -empty

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

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

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

16 голосов
/ 25 октября 2013

Просто найдите пустые каталоги

Чтобы просто найти пустые каталоги (как указано в заголовке вопроса), ответ 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 {} `;`

Каталог пуст?

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

  1. [ $(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
      
  2. (( ${#files} ))

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

    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
    

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

  3. [ $(ls -A your/dir) ]

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

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

    или версия однострочного bashism:

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

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

2 голосов
/ 11 мая 2010

Эта рекурсивная функция, похоже, справилась бы с задачей:

# 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, функция включит этот каталог в свои результаты.

1 голос
/ 24 апреля 2014

Как насчет rmdir *? Эта команда не будет выполнена в непустых каталогах.

0 голосов
/ 11 мая 2010
find . -name -type d -ls |awk '($2==0){print $11}'
0 голосов
/ 11 мая 2010

простой подход будет,

$ [ "$(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"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...