我必须保留包含特定子目录中文件的所有目录,但删除子目录为空的所有目录。
更具体地说,结构如下:
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
下面的脚本将完全按照您描述的方式执行:
- 列出目录内的文件夹
在每个文件夹中查找名为“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
使用
- 将脚本复制到一个空文件中,另存为
delete_empty.py
使用(完整!)目录(包含您的子目录,示例中为 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))
编辑
此外,根据评论的要求,版本将检查多个子目录(名称)。
如果目录包含任何列出的(非空)子目录中,则保留该目录。否则,它将被删除。
使用
- 将脚本复制到一个空文件中,另存为
delete_empty.py
使用(完整!)目录(包含您的子目录,示例中为 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
使用find
和xargs
:
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*/
确保您只在目录上工作,因此其他文件不会受到影响。