Удалить все файлы / каталоги, кроме двух определенных каталогов - PullRequest
5 голосов
/ 14 мая 2009

Итак, кажется, есть несколько вопросов об удалении файлов / каталогов, соответствующих определенным случаям, но я ищу с точностью до наоборот: удалите ВСЕ в папке, которая не соответствует моим предоставленным примерам.

Например, вот пример дерева каталогов:

.
|-- coke
|   |-- diet
|   |-- regular
|   `-- vanilla
|-- icecream
|   |-- chocolate
|   |-- cookiedough
|   |-- cupcake
|   |   |-- file1.txt
|   |   |-- file2.txt
|   |   |-- file3.txt
|   |   |-- file4.txt
|   |   `-- file5.txt
|   `-- vanilla
|-- lol.txt
|-- mtndew
|   |-- classic
|   |-- codered
|   |-- livewire
|   |   |-- file1.txt
|   |   |-- file2.txt
|   |   |-- file3.txt
|   |   |-- file4.txt
|   |   `-- file5.txt
|   `-- throwback
`-- pepsi
    |-- blue
    |-- classic
    |-- diet
    `-- throwback

Я хочу удалить все, кроме файлов в test / icecream / cupcake / и test / mtndew / livewire /. Все остальное может идти, включая структуру каталогов. Итак, как мне этого добиться? Языки, на которых я был бы не против: bash или python.

Ответы [ 10 ]

6 голосов
/ 14 мая 2009

Эта команда оставит только нужные файлы в их исходных каталогах:

find test \( ! -path "test/mtndew/livewire/*" ! -path "test/icecream/cupcake/*" \) -delete

Нет необходимости в cpio. Он работает в Ubuntu, Debian 5 и Mac OS X.

В Linux он сообщит, что не может удалить непустые каталоги, что является желаемым результатом. В Mac OS X он будет делать все правильно.

3 голосов
/ 14 мая 2009

find s -prune приходит на ум, но мучительно работать с определенными путями (icecream/cupcake/), а не с конкретными каталогами (cupcake/).

Лично я бы просто использовал cpio и жестко связал (чтобы избежать необходимости их копировать) файлы в каталогах, которые вы хотите сохранить в новом дереве, а затем удалил старое:

find test -path 'test/icecream/cupcake/*' -o -path 'test/mtndew/livewire/*' | cpio -padluv test-keep
rm -rf test

Это также сохранит существующую структуру каталогов для каталогов, которые вы собираетесь хранить.

3 голосов
/ 14 мая 2009

Все «кроме» - вот почему у нас есть операторы if; и почему список каталогов os.walk является изменяемым списком.

for path, dirs, files in os.walk( 'root' ):
    if 'coke' in dirs:
        dirs.remove('coke')
        dirs.remove('pepsi')
2 голосов
/ 27 августа 2010
find /path/to/test/ -depth -mindepth 1 \
! -path "/path/to/test/icecream/cupcake/*" \
! -path "/path/to/test/icecream/cupcake" \
! -path "/path/to/test/icecream" \
! -path "/path/to/test/mtndew/livewire/*" \
! -path "/path/to/test/mtndew/livewire" \
! -path "/path/to/test/mtndew"
 -delete -print

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

2 голосов
/ 14 мая 2009

Переместите материал, который вы хотите сохранить, в другое место, затем удалите то, что осталось.

2 голосов
/ 14 мая 2009

Вы можете сделать что-нибудь, основываясь на функции Python os.walk :

import os
for root, dirs, files in os.walk(top, topdown=False):
    for name in files:
        os.remove(os.path.join(root, name))
    for name in dirs:
        os.rmdir(os.path.join(root, name))

... просто добавьте что-нибудь, чтобы игнорировать интересующие вас пути.

0 голосов
/ 15 мая 2009

Как и другие, я использовал os.walk и os.path.join для создания списка файлов, которые нужно удалить, с помощью fnmatch.fnmatch для выбора файлов, которые должны быть включены или исключены:

#-------------------------------#
# make list of files to display #
#-------------------------------#
displayList = []
for imageDir in args :
    for root,dirs,files in  os.walk(imageDir) :
        for filename in files :
            pathname = os.path.join( root, filename ) 
            if fnmatch.fnmatch( pathname, options.includePattern ) :
                displayList.append( pathname )


#----# now filter out excluded patterns #----#
try :
    if len(options.excludePattern) > 0 :
        for pattern in options.excludePattern :
            displayList = [pathname for pathname in displayList if not fnmatch.fnmatch( pathname, pattern ) ]
except ( AttributeError, TypeError ) :
    pass

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

Здесь я создал список файлов, прежде чем что-то с ним делать, но вы можете обрабатывать файлы по мере их создания.

Блок try / исключением ... существует в том случае, если в моем экземпляре класса параметров отсутствует шаблон исключения или если он вызывает исключение в fnmatch, потому что это неправильный тип.

Ограничением этого метода является то, что сначала включает файлов, соответствующих шаблону, , затем исключает . Если вам нужна большая гибкость, чем эта (включая соответствующий шаблон a, но не шаблон b, если не шаблон c ...), тогда приведенный выше фрагмент не до него. Фактически, работая с этим упражнением, вы начинаете понимать, почему синтаксис команды find такой, какой он есть. Кажется неуклюжим, но на самом деле это именно тот способ.

Но если вы генерируете список, вы можете фильтровать его в соответствии с любыми правилами включения / исключения, которые вам нужны.

Одна приятная вещь при создании списка - вы можете проверить его, прежде чем продолжить удаление. Это своего рода опция --dryrun. Вы можете сделать это в интерактивном режиме в интерпретаторе python, распечатать список, чтобы посмотреть, как он выглядит, применить следующий фильтр, посмотреть, удалил ли он слишком много или слишком мало и т. Д.

0 голосов
/ 14 мая 2009

У меня это работает с find, используя два шага: сначала удалите разрешенные файлы, затем их пустые каталоги!

find -x -E ~/Desktop/test -not \( -type d -regex '.*/(cupcake|livewire)/*.*' -prune \) -print0 | xargs -0 ls -1 -dG 

# delete the files first

# Mac OS X 10.4 
find -x -E ~/Desktop/test -not \( -type d -regex '.*/(cupcake|livewire)/*.*' -prune \) -type f -exec /bin/rm -fv '{}' \; 

# Mac OS X 10.5 
find -x -E ~/Desktop/test -not \( -type d -regex '.*/(cupcake|livewire)/*.*' -prune \) -type f -exec /bin/rm -fv '{}' + 

# delete empty directories 
find -x ~/Desktop/test -type d -empty -delete 
0 голосов
/ 14 мая 2009

Один пользователь для решения проблемы:

найти. | grep -v "тест / мороженое / кекс /" | grep -v "test / mtndew / livewire /" | xargs rm -r

Удалено, так как не работает

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

Несколько лучшее решение:

find . |sed "s/.*/rm '&'/"|grep -v "rm './test/icecream/cupcake/"| grep -v "rm './test/mtndew/livewire/"|sh

На самом деле не проверено, если оно сломается, вы сохраните обе части.

Редактировать: поскольку Деннис указывает не только на две части, на которые он разбивается :-) исправил опечатки во втором примере и удалил первый

0 голосов
/ 14 мая 2009

использование find.

Ваша команда будет выглядеть примерно так:

find $directory \( -prune 'some pattern' \) -delete
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...