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

Der*_*mes 11 command-line directory find

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

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

A
|
|--------312311
|       |
|       |----Recording
|       |----a.txt
|       |----b.txt
|
|
|--------453453
|       |----Recording
|                   |
|                   |-------a.mp3
|       |----a.txt
|       |----b.txt
|
|
|--------566532
|       |----Recording
|       |----a.txt
|       |----b.txt
Run Code Online (Sandbox Code Playgroud)

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

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

Jac*_*ijm 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
Run Code Online (Sandbox Code Playgroud)

将导致:

A
|
|
|--------635623
|       |----Recording
|                   |
|                   |-------a.mp3
|       |----a.txt
|       |----b.txt
|
|
|--------Monkey.txt
Run Code Online (Sandbox Code Playgroud)

剧本

#!/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
Run Code Online (Sandbox Code Playgroud)

使用

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

    python3 /path/to/delete_empty.py /path/to/directory
    
    Run Code Online (Sandbox Code Playgroud)

就是这样。

解释

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

python3 /path/to/delete_empty.py /path/to/directory
Run Code Online (Sandbox Code Playgroud)

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

os.listdir(dr)
Run Code Online (Sandbox Code Playgroud)

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

if not os.listdir(path(dr, d, "Recording"))
Run Code Online (Sandbox Code Playgroud)

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

except NotADirectoryError
    pass
Run Code Online (Sandbox Code Playgroud)

如果文件夹“录音”存在为空,则删除上级文件夹:

FileNotFoundError
    shutil.rmtree(path(dr,d))
Run Code Online (Sandbox Code Playgroud)

编辑

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

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

使用

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

    python3 /path/to/delete_empty.py /path/to/directory <subdir1> <subdir2> <subdir3>
    
    Run Code Online (Sandbox Code Playgroud)

就是这样。

剧本

if not os.listdir(path(dr, d, "Recording")):
    shutil.rmtree(path(dr,d))
Run Code Online (Sandbox Code Playgroud)

笔记

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


ste*_*ver 11

使用findxargs

find A -type d -name 'Recording' -empty -printf '%h\0' | xargs -0 echo rm -rf
Run Code Online (Sandbox Code Playgroud)

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
              ".".
Run Code Online (Sandbox Code Playgroud)

例如:给定

$ 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
Run Code Online (Sandbox Code Playgroud)

然后

$ 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
Run Code Online (Sandbox Code Playgroud)