【问题标题】: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个集合,确定这三个集合的交集,然后删除原始列表中的那个交集。这样一来,您就剩下三组,可以准确地告诉您需要在每个文件夹中删除哪些文件。

标签: python windows batch-file delete-file


【解决方案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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-27
        • 2019-10-19
        • 1970-01-01
        相关资源
        最近更新 更多