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

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

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

更具体地说,结构如下:

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

子目录可能包含文件,也可能不包含文件。因此,我需要删除整个目录,如“312311”和“566532”,只留下“453453”及其所有数据,因为它在“Recording”文件夹中有一个文件,而这对我来说是一个特定的目录。

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

答案1

下面的脚本将完全按照您描述的方式执行:

  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

或者如果文件夹“Recording”根本不存在:

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. 使用(完整!)目录(包含您的子目录,示例中为 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))

笔记

请首先在测试目录上运行以确保它完全按照您的要求执行。

答案2

使用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

答案3

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

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

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

相关内容