如果特定的子目录为空,则删除父目录(非空)


11

我必须将包含文件的所有目录保留在特定的子目录中,但要删除其余所有子目录为空的目录。

更具体地说,这里是结构:

A
|
|--------312311
|       |
|       |----Recording
|       |----a.txt
|       |----b.txt
|
|
|--------453453
|       |----Recording
|                   |
|                   |-------a.mp3
|       |----a.txt
|       |----b.txt
|
|
|--------566532
|       |----Recording
|       |----a.txt
|       |----b.txt

子目录可以包含文件,也可以不包含文件。因此,我需要删除整个目录,例如“ 312311”和“ 566532”,并且只保留“ 453453”中的所有数据,因为它在“录制”文件夹中有一个文件,这是我的特定目录。

我看到了很多帖子,但是它链接到许多特定的文件名。任何帮助将不胜感激,因为我每周需要做很多次。


记录始终位于目录的第一层吗?另外:所有文件夹都位于主目录的第一层吗?
雅各布·弗利姆

A是顶层目录,其中包含编号的目录。并在编号目录中包含“ Recording”文件夹以及一些“ txt”文件,例如。而在“录音”它可能会或可能不会包含文件..
德里克·詹姆斯

您会删除文字图片并将实际文字放入您的问题中吗?文字图片对我们来说很麻烦。除了其他固有的便利之外,使用实际文本实质上更加方便。
LD詹姆斯

我也按照詹姆斯的要求做了同样的事情
。–德里克·

Answers:


12

下面的脚本将完全按照您的描述进行操作:

  1. 列出目录中的文件夹
  2. 在每个文件夹中查找名为“ Recording”的文件夹

    • 如果存在为空,则删除其上级文件夹
    • 如果它存在,它还会删除其卓越的文件夹
    • A中第一层的文件不会被删除。

在图像中:

A
|
|--------123456
|       |
|       |----Recording
|       |----a.txt
|       |----b.txt
|
|
|--------635623
|       |----Recording
|                   |
|                   |-------a.mp3
|       |----a.txt
|       |----b.txt
|
|
|--------123456
|       |----Recording
|       |----a.txt
|       |----b.txt
|
|--------Monkey.txt

将导致:

A
|
|
|--------635623
|       |----Recording
|                   |
|                   |-------a.mp3
|       |----a.txt
|       |----b.txt
|
|
|--------Monkey.txt

剧本

#!/usr/bin/env python3
import os
import sys
import shutil

dr = sys.argv[1]

def path(*args):
    return os.path.join(*args)

for d in os.listdir(dr):
    try:
        if not os.listdir(path(dr, d, "Recording")):
            shutil.rmtree(path(dr,d))
    except FileNotFoundError:
        shutil.rmtree(path(dr,d))
    except NotADirectoryError:
        pass

使用

  1. 将脚本复制到一个空文件中,另存为 delete_empty.py
  2. 使用以下命令以(完整!)目录(包含子目录,在示例中为A)作为参数运行它:

    python3 /path/to/delete_empty.py /path/to/directory
    

而已。

说明

将文件夹“ A”的内容提供给脚本,

os.listdir(dr)

将列出其子目录(和文件)。然后:

if not os.listdir(path(dr, d, "Recording"))

将尝试列出每个(子)文件夹的内容,如果该项目是文件,则将引发错误:

except NotADirectoryError
    pass

或根本不存在“录制”文件夹:

FileNotFoundError
    shutil.rmtree(path(dr,d))

如果文件夹“ Recording”存在为空,则上级文件夹将被删除:

if not os.listdir(path(dr, d, "Recording")):
    shutil.rmtree(path(dr,d))

编辑

此外,根据注释中的要求,该版本将检查多个子目录(名称)。

如果目录包含任何列出的(非空)子目录,则保留该目录。否则它将被删除。

使用

  1. 将脚本复制到一个空文件中,另存为 delete_empty.py
  2. 使用(full!)目录(包含子目录,在示例中为A)运行该目录,并使用以下命令将子目录的名称作为参数:

    python3 /path/to/delete_empty.py /path/to/directory <subdir1> <subdir2> <subdir3>
    

而已。

剧本

#!/usr/bin/env python3
import shutil
import os
import sys

dr = sys.argv[1]; matches = sys.argv[2:]

def path(*args):
    return os.path.join(*args)

for d in os.listdir(dr):
    # delete directory *unless* either one of the listed subdirs has files
    keep = False
    # check for each of the listed subdirs(names)
    for name in matches:
        try:
            if os.listdir(path(dr, d, name)):
                keep = True
                break
        except NotADirectoryError:
            # if the item is not a dir, no use for other names to check
            keep = True
            break
        except FileNotFoundError:
            # if the name (subdir) does not exist, check for the next
            pass
    if not keep:
        # if there is no reason to keep --> delete
        shutil.rmtree(path(dr,d))

注意

请首先在测试目录上运行,以确保它完全符合您的要求。


这段代码确实有帮助,并且按上述方式工作。感谢您的代码。真的很有帮助。
德里克·詹姆斯

假设如果我需要保留并检查两个或更多文件夹,那么如何在此代码中执行操作?添加“或”或“管道” '在某处..建议食用!
德里克·詹姆斯

大家好,@ DerekJames只需进行少量修改,我将在今天下午发布。
雅各布·弗利姆

@Derek,等等,如果任何一个文件夹为空或全部为空,是否应删除上级文件夹?一个上层目录中可能有多个?
雅各布·弗利姆

假设@Jacob,我有两个文件夹“ Recording”和“ Video”。它应该检查两个。如果任何子文件夹包含文件,则不会删除文件夹“ 635623”。并且还能够添加多个文件夹,以检查是否是可以做到的..
德里克·詹姆斯

11

使用findxargs

find A -type d -name 'Recording' -empty -printf '%h\0' | xargs -0 echo rm -rf

echo一旦确定可以识别正确的目录,就删除它)。该printf '%h\0部分打印(空结尾的)父目录-来自man find

       %h     Leading directories of file's name (all but the last ele‐
              ment).  If the file name contains no slashes (since it is
              in  the  current  directory)  the %h specifier expands to
              ".".

例如:给定

$ tree A
A
├── 312311
│   ├── a.txt
│   ├── b.txt
│   └── Recording
├── 453453
│   ├── a.txt
│   ├── b.txt
│   └── Recording
│       └── a.mp3
└── 566532
    ├── a.txt
    ├── b.txt
    └── Recording

6 directories, 7 files

然后

$ find A -type d -name 'Recording' -empty -printf '%h\0' | xargs -0 rm -rf
$ 
$ tree A
A
└── 453453
    ├── a.txt
    ├── b.txt
    └── Recording
        └── a.mp3

2 directories, 3 files

查找A型d-名称'Recording'-空-printf'%h \ 0'| xargs -0 echo rm -rf这只是打印“ rm -rf”并找到A -type d -name'Recording'-empty -printf'%h \ 0'| xargs的-0室射频是不工作...我做得不对..
德里克·詹姆斯

@DerekJames您需要用实际目录替换A。
Jacob Vlijm

因为OP给文件名加上数字,所以用正则表达式代替Recording名称可以[\d]*吗?
乔治·乌德森

@JacobVlijm:我已替换为实际目录,但仍未出错?
德里克·詹姆斯

@DerekJames真奇怪!它可以在我的系统上运行,但是您可能忘记了先将CD插入目录?等等,这没关系……
Jacob Vlijm

3

这是一个更简单的bash解决方案:

for d in */; do rmdir "$d/Recording" && rm -r "$d"; done

之所以起作用,是因为rmdir如果目录不为空,它将失败,并且除非成功,否则&&将阻止rm -r执行rmdir。全局*/确保您仅在目录上工作,因此其他文件不会受到影响。


聪明的思维!+1
Jacob Vlijm '17
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.