【问题标题】:Python: How to use output of "listfiles" to delete/ move/ etc. filesPython:如何使用“listfiles”的输出来删除/移动/等文件
【发布时间】:2023-04-20 02:19:02
【问题描述】:

背景:

我的目标是在两个不同的文件夹(没有子文件夹)中找到重复的文件。为此,我使用以下 Python 脚本:

###Check ob alle Archive noch vorhanden oder ob Daten bei Check gelöscht wurden
def listfiles(path):
    files = []
    for dirName, subdirList, fileList in os.walk(path):
        dir = dirName.replace(path, '')
        for fname in fileList:
                if fname.endswith("_GIS.7z"):
                    files.append(os.path.join(dir, fname))
    return files

x = listfiles(root)
y = listfiles(backupfolderGIS)

#q = [filename for filename in x if filename not in y]

files_only_in_x = set(x) - set(y) 
files_only_in_y = set(y) - set(x)
files_only_in_either = set(x) ^ set(y)
files_in_both = set(x) & set(y)
all_files = set(x) | set(y)

print "Alle Datein:"
print all_files
print " "

print "Nur im Zwischenspeicher:"
print files_only_in_x
print " "

print "Nur im Backupordner:"
print files_only_in_y
print " "

print "Nur einem von beiden Ordnern:"
print files_only_in_either
print " "

print "In beiden Ordnern:"
print files_in_both
print " "

相关的输出变量/列表是files_in_both(文件夹);它向我展示了复制品;如果我使用print,它看起来像set(['NameoftheProject_GIS.7z', 'NameofanotherProject_GIS.7z'])

问题:

如何使用此输出/信息(目录中的重复文件)删除/移动它们?例如文件夹backupfolderGIS/列表files_in_both中的文件NameoftheProject_GIS.7zNameofanotherProject_GIS.7z

【问题讨论】:

    标签: python list directory delete-file os.walk


    【解决方案1】:

    os.walk 递归检查从您传递的根目录开始的所有文件夹和子文件夹,您想检查 两个不同的文件夹(没有子文件夹) 所以只需使用 glob 搜索每个文件夹em>,如果你想移动你可以使用shutil.move

    from glob import iglob
    from os import path
    from shutil import move
    
    pt1, pt2 = "/path_1", "path_2"
    dupe = set(map(path.basename, iglob("/path_1./*_GIS.7z"))).intersection(map(path.basename, iglob("/path_2./*_GIS.7z")))
    
    for fle in dupe:
        # move(src, dest)
        move(path.join(pt1, fle), "wherever")
    

    或者删除使用os.remove:

    for fle in dupe:
        os.remove(path.join(pt1, fle))
    

    如果您想从 pt2 移动/删除文件,请将其传递给 path.join 以代替 pt1。

    您也可以将 str.endwithos.listdir 一起使用:

    dupe = set(fname for fname in os.listdir(pt1) if fname.endswith("_GIS.7z")).intersection(fname for fname in os.listdir(pt2) if fname.endswith("_GIS.7z"))
    

    为了避免重复,你可以把它放在一个函数中:

    from shutil import move
    from os import path, listdir
    def listfiles(path, end):
        return set(fname for fname in listdir(path) if fname.endswith(end))
    
    for fle in listfiles(pt1,"_GIS.7z").intersection(listfiles(pt2, "_GIS.7z")):
        move(path.join(t1, fle), "wherever")
    

    现在,如果您确实想检查所有文件夹中是否有具有相同基本名称的文件以及某些重复名称,则需要记录完整路径,您可以使用 defaultdict 按基本名称对所有常见文件进行分组:

    from os import path, walk
    from collections import defaultdict
    
    def listfiles(pth, end):
        files = defaultdict(list)
        for dirName, subdirList, fileList in walk(pth):
            for fname in fileList:
                if fname.endswith(end):
                    files[fname].append(path.join(dirName, fname))
        return files
    

    你会得到一个字典,其中键是基本名称,值是文件列表,每个文件都有完整路径,任何包含多个值的列表都意味着你至少有两个同名文件,但你应该记住具有相同的基本名称并不意味着文件实际上是相同的。

    【讨论】:

    • 啊,没有评论的 dv 以获得正确的答案,差评;)
    • 感谢您解决了我的问题(非常快)。用我检查文件夹的方式来解决它会很好,但你的方式运行良好且快速!不知道为什么有人投票给你,会评价它;在接受它作为最佳答案之前,将等待 24 小时或更长时间。
    • @André,如果你只有两个文件夹,那么你应该使用 glob 或 os.listdir,walk 用于递归检查。如果您确实想在具有相同基本名称的任何地方查找文件,您可以使用 os.walk 方法,一种方法是使用 dict,我将在一分钟内添加一个示例
    • 感谢您的宝贵时间!根据需要工作。我接受它作为答案。从德国到爱尔兰的问候
    • 我已经了解了“文件实际上并不相同”,但因为这部分脚本属于备份脚本,其中文件不会相同 - 除了这个名字 - 它对我有用。
    最近更新 更多