删除除两个特定目录之外的所有文件/目录

时间:2009-05-14 09:25:37

标签: python linux bash

所以,似乎有一些问题要求删除与某些情况匹配的文件/目录,但我正在寻找完全相反的方法:在与我提供的示例不匹配的文件夹中删除所有内容。

例如,这是一个示例目录树:

.
|-- 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 个答案:

答案 0 :(得分:6)

此命令仅在原始目录中保留所需文件:

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

不需要cpio。它适用于Ubuntu,Debian 5和Mac OS X.

在Linux上,它会报告它无法删除非空目录,这正是所需的结果。在Mac OS X上,它会悄悄地做正确的事情。

答案 1 :(得分:3)

“除了”之外的一切都是为什么我们有if语句;以及为什么os.walk的目录列表是一个可变列表。

for path, dirs, files in os.walk( 'root' ):
    if 'coke' in dirs:
        dirs.remove('coke')
        dirs.remove('pepsi')

答案 2 :(得分:3)

我想到了{p> find的{​​{1}},但要让它适用于特定路径(-prune)而不是特定目录(icecream/cupcake/)是一件痛苦的事。

就个人而言,我只是使用cupcake/并硬链接(以避免必须复制它们)要保留到新树的目录中的文件,然后删除旧树:

cpio

这也将保留您打算保留的目录的现有目录结构。

答案 3 :(得分:2)

您可以根据Python's os.walk function执行某些操作:

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))

...只需添加一些内容即可忽略您感兴趣的路径。

答案 4 :(得分:2)

将要保留的内容移动到其他位置,然后删除剩下的内容。

答案 5 :(得分:2)

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

编写所有要保留的路径有点乏味,但这是单独使用find的唯一方法。

答案 6 :(得分:0)

使用find

您的命令将类似于:

find $directory \( -prune 'some pattern' \) -delete

答案 7 :(得分:0)

解决问题的oneliner:

找到。 | grep -v“test / icecream / cupcake /”| 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

没有经过实际测试,如果它破坏你就可以保留这两个部分。

编辑:正如丹尼斯指出的那样,不仅有两个部分被打破:-)更正了第二个例子中的拼写错误并删除了第一个

答案 8 :(得分:0)

使用两个步骤查找它对我有用:首先删除允许的文件,然后删除它们的空目录!

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 

答案 9 :(得分:0)

与其他人一样,我使用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 / except块...如果我的选项类实例没有排除模式,或者它在fnmatch中导致异常,因为它是错误的类型。

此方法的一个限制是,首先包含与模式匹配的文件,然后排除。如果你需要比这更灵活(包括匹配模式a,但不包括模式b,除非模式c ...),那么上面的片段不符合它。实际上,通过本练习,您将开始了解查找命令语法的原因。看起来很笨,但实际上它正是这样做的方式。

但是如果您生成列表,则可以根据所需的包含/排除规则对其进行过滤。

生成列表的一个好处是您可以在继续删除之前进行检查。这有点像'--dryrun'选项。您可以在python解释器中以交互方式执行此操作,打印列表以查看其外观,应用下一个过滤器,查看它是否已删除太多或太少等等。