如何检查多个文件夹并删除具有唯一文件名的任何文件?
Posted
技术标签:
【中文标题】如何检查多个文件夹并删除具有唯一文件名的任何文件?【英文标题】:How do I check multiple folders and delete any files with unique file names? 【发布时间】:2021-11-17 07:49:21 【问题描述】:我正在从检查系统上的多个摄像头捕获小部件的图像。如果检查不成功,则不会保存图像。图像以小部件的序列号命名。
所以我的文件夹结构可能看起来像
相机1 1.tif 2.tif 4.tif 相机2 2.tif 3.tif 4.tif 相机3 1.tif 2.tif 3.tif 4.tif我希望能够删除所有三个文件夹中都不匹配的图像。我不介意两次运行该解决方案,一次在相机 1 和相机 2 之间,然后再次使用相机 2 和相机 3。
我希望只剩下以下文件夹结构。
相机1 2.tif 4.tif 相机2 2.tif 4.tif 相机3 2.tif 4.tif每个文件夹中有大约 12,000 个文件供分析,可能有 2%-3% 的错误需要删除才能继续分析。
我不介意需要付款、python、命令行等的预打包解决方案。
非常感谢!
【问题讨论】:
没有downvote your question because no attempt was made,因为你是一个新的贡献者,但通常我们希望你至少提出一个honest attempt at the solution,然后然后问具体问题) 关于您的实施。 首先您必须阅读所有文件名。接下来,您应该使用此文件名创建带有"1.tif":["Camera1", "Camera3"], "2.tif":[...]
等列表的字典,接下来您应该检查列表中哪些文件名的值少于 3 个,然后您可以从这些文件夹中删除这些文件名。
既然在内存中加载几个列表文件的数量不会引起问题,那么如何使用文件夹的内容创建3个集合,确定这三个集合的交集,然后删除原始列表中的那个交集。这样一来,您就剩下三组,可以准确地告诉您需要在每个文件夹中删除哪些文件。
【参考方案1】:
按照 cmets 的建议,下次您在 SO 上提出问题时,请先自己试一试,并询问任何问题 - 这样您可以了解更多信息。
这是一个开始,如下所示,下面的代码使用文件夹的内容创建 3 个集合,确定这三个集合的交集,然后从原始集合中删除该交集。结果会准确告诉您每个文件夹中需要删除哪些文件:
from pathlib import Path
def find_unmatched(dirs):
# list the (file) contents of the folders
contents =
for d in dirs:
contents[d] = set(str(n.name) for n in Path(d).glob('*') if n.is_file())
# decide what the folders have in common
all_files = list(contents.values())
common = all_files[0]
for d_contents in all_files[1:]:
common = common.intersection(d_contents)
# create a dictionary that tells you what to remove
return d: files - common for d, files in contents.items()
to_remove = find_unmatched(['photos/Camera1', 'photos/Camera2', 'photos/Camera3'])
print(to_remove)
结果(假设您的示例中的文件夹位于名为 photos
的文件夹中):
'photos/Camera1': '1.tif', 'photos/Camera2': '3.tif', 'photos/Camera3': '1.tif', '3.tif'
实际上删除文件是一些您可能自己弄清楚的代码。
【讨论】:
【参考方案2】:如前所述,您应该自己努力解决问题,遇到困难时寻求帮助。不过,我现在有一些空闲时间,所以我写了一个完整的 Batch 解决方案:
@echo off
setlocal EnableDelayedExpansion
rem Process files in Camera1 folder and populate "F" array elements = 1
cd Camera1
for %%a in (*.tif) do set "F[%%~Na]=1"
rem Process files in Camera2 and *accumulate* files to "F" array
cd ..\Camera2
for %%a in (*.tif) do set /A "F[%%~Na]+=1"
rem Process files in Camera3 and accumulate files to "F" array
rem if counter == 3 then file is OK: remove "F" element
rem else: delete file
rem if counter == 1: remove "F" element
cd ..\Camera3
for %%a in (*.tif) do (
set /A "F[%%~Na]+=1"
if !F[%%~Na]! equ 3 (
set "F[%%~Na]="
) else (
del %%a
if !F[%%~Na]! equ 1 set "F[%%~Na]="
)
)
rem Remove files of "F" array in both Camera1 and Camera2 folders, ignoring error messages
cd ..
(for /F "tokens=2 delims=[]" %%a in ('set F[') do (
del Camera1\%%a.tif
del Camera2\%%a.tif
)) 2>nul
请报告结果...
【讨论】:
嘿@Aacini,这就像一个魅力。从脚本中创建了三个同名文件夹并填充了工作的一个子集,运行未经编辑的脚本,它们都完美无缺。谢谢您的帮助!此外,在展示我以前的作品方面,我绝对吸取了教训!感谢您的耐心等待! 请注意,批处理文件存在大量环境变量的速度问题。使用您的 ~12000 个文件运行此程序并检查经过的时间。也许会花费太多时间,并且需要修改方法... 嘿@Aacini,解析 12K 文件大约需要 3 分钟。再次,非常感谢您的宝贵时间,工作得很好! 我可以请你帮个忙吗?你能用我这里的另一种方法(基于文件的方法)运行同一组文件并比较时间吗?这一点对我来说很重要。谢谢!【参考方案3】:虽然方法很简单,但可能不是最快的:
@echo off
rem // Change into root directory:
pushd "%~dp0." && (
rem // Outer loop through target directories:
for /D %%J in ("Camera?") do (
rem // Create temporary file with matching contents of current directory:
dir /B /A:-D-H-S "%%~J\*.tif" > "%TEMP%\%%~nxJ.log"
rem // Inner loop through target directories:
for /D %%I in ("Camera?") do (
rem // Avoid comparing current directory with itself:
if /I not "%%~I"=="%%~J" (
rem /* List these files inside of the directory of the inner loop where no
rem respective files inside of the directory of the outer loop are found: */
for /F "delims= eol=|" %%K in ('
dir /B /A:-D-H-S "%%~I\*.tif" ^| findstr /L /I /V /G:"%TEMP%\%%~nxJ.log"
') do (
rem // Actually delete current file:
ECHO del "%%~I\%%K"
)
)
)
rem // Delete temporary file:
del "%TEMP%\%%~nxJ.log"
)
rem // Return from root directory:
popd
)
exit /B
关键是目标目录上的两个嵌套循环,以便相互比较,findstr
command 用于从一个目录中过滤掉另一个目录中不存在的文件。
测试正确的输出后,删除大写的ECHO
命令!
【讨论】:
【参考方案4】:这个新方法是基于文本文件的,所以它应该比环境变量方法运行得更快。在 12000 行文件(6 次!)中搜索缺失名称的繁重任务由 findstr
命令执行。
这种方法也比较简单,可以匹配3个以上的文件夹。
@echo off
setlocal EnableDelayedExpansion
rem Get a list of directories and create temp files with their contents
set "directories="
for /D %%d in (Camera?) do (
set "directories=!directories! %%d"
dir /B "%%d\*.tif" > %%d.txt
)
rem Process the directories "d"
for %%d in (%directories%) do (
rem Compare this directory "d" vs. the others "D"
for %%D in (!directories:%%d=!) do (
rem Remove files in this "d" that not exists in the other "D"
(for /F %%f in ('findstr /V /G:%%D.txt %%d.txt') do del "%%d\%%f") 2>nul
)
)
for %%d in (%directories%) do del %%d
【讨论】:
以上是关于如何检查多个文件夹并删除具有唯一文件名的任何文件?的主要内容,如果未能解决你的问题,请参考以下文章