Pythonで画像ファイルの仕分け(3)


まえがき

前回、削除対象リストのファイルを生成するところまで終わった。ファイルの内容はこんな感じだ。

\TMP\200104\delete.txt
C:\TMP\IMG_2607(1).jpg
C:\TMP\IMG_2608(1).jpg
\TMP\200105\delete.txt
C:\TMP\IMG_2610(1).jpg
C:\TMP\IMG_2610(2).jpg
C:\TMP\IMG_2611(1).jpg

各年月(yyyymm)フォルダに削除したいファイルのフルパスが一行ずつ書かれているdelete.txtがあるので、これを読みだして削除するのみである。まだ試験段階なのでテストフォルダを対象に処理を書いてみる。

Python3で書いてみる

Python : 3.8.3

DeleteAll.py
import glob
import os

if __name__ == "__main__":
    files = glob.glob("C:\\tmp\\**\\delete.txt", recursive=True)

    for file in files:
        with open(file, "r") as f:
            for line in f.readlines():
                os.remove(line.strip())

glob様様。readlines()で読むと末尾に'\n'がくっつくのは何故?(ちょっと邪魔)

C#で書いてみる

C# : 8.0(Microsoft Visual Studio Community 2019)

DeleteAll.cs
using System;
using System.IO;
using System.Text;

namespace DeleteAll
{
    class DeleteAll
    {
        static void Main()
        {
            var files = Directory.GetFiles(@"c:\tmp", "delete.txt", SearchOption.AllDirectories);

            foreach (var file in files)
            {
                foreach (var line in File.ReadAllLines(file, Encoding.GetEncoding("Shift-JIS")))
                {
                    File.Delete(line);
                }
            }
        }
    }
}

普段は思わないがこうしてPythonと並べてみると括弧がとても邪魔なものに見えてきた・・・

VB6で書いてみる(FileSystemObject使用)

VisualBasic : 6.0

DeleteAll.bas
Option Explicit

Private colFiles As Collection

Public Sub Main()
    Set colFiles = New Collection
    Call GetFiles("C:\TMP\")
    Call DeleteFiles(colFiles)
End Sub

Private Sub GetFiles(ByVal strSearchPath As String)
    Dim FSO As FileSystemObject

    Set FSO = New FileSystemObject

    Dim objSubFolder As Folder

    For Each objSubFolder In FSO.GetFolder(strSearchPath).SubFolders
        Call GetFiles(objSubFolder.Path)
    Next

    Dim objFile As file

    For Each objFile In FSO.GetFolder(strSearchPath).files
        If LCase(objFile.Name) = "delete.txt" Then
            Call colFiles.Add(FSO.BuildPath(strSearchPath, objFile.Name))
        End If
    Next
End Sub

Private Sub DeleteFiles(ByVal files As Collection)
    Dim FSO As FileSystemObject
    Dim vntFile As Variant

    Set FSO = New FileSystemObject

    For Each vntFile In files
        With FSO.GetFile(vntFile).OpenAsTextStream(ForReading)
            Do
                Kill .ReadLine()
            Loop Until (.AtEndOfLine())
        End With
    Next
End Sub

古式ゆかしきハンガリアン記法で。再帰検索を自前実装する必要があって大変面倒。これでFileSystemObjectを使わない縛りにでもしたら大事になります。GetFiles()内の変数宣言は登場する直前にDim宣言するよう書いていますが古いVB6ソースではメソッド冒頭でまとめて宣言を書く習わしです。多分C->VBと流れた人の流儀なのかと思いますがそんな風に書いてるソースに限って1メソッド500行とかになってるクソコードを良く見かけます。

バッチファイルで書いてみる

DeleteAll.bat
@echo off
cd \tmp
for /f "usebackq" %%i in (`dir /s /b delete.txt`) do (for /f %%j in (%%i) do del %%j)

バッチファイルのなんとシンプルなことか。代わりに書式は若干難解ではあるけれど。

あとがき

これにて本件完了。さて、次は何に取り組もうか。