有没有办法从一个文件夹中删除另一个文件夹中的文件?

有没有办法从一个文件夹中删除另一个文件夹中的文件?

假设我从文件夹 A 复制并粘贴文件,其中包括:

文件夹 A:

file1.cfg  
file2.txt  
file3.esp  
file4.bsa  

进入文件夹 B,更新后包含:

文件夹 B:

apples.mp3  
file1.cfg    *
file2.txt    *
file3.esp    *
file4.bsa    *
turtles.jpg

有没有办法删除文件夹 B 中文件夹 A 中的所有文件(标有 *)?除了手动选择每个文件并删除,或者在复制粘贴后立即按 ctrl-Z 键

我更喜欢 Windows 方法或者一些可以做到这一点的软件

谢谢!

答案1

有一款免费软件叫合并。您可以使用该软件来匹配重复项。首先,使用FileOpen,选择两个目录,左侧是要保留的文件文件夹,右侧是不需要保留的文件文件夹。然后,转到View,取消选择Show Different ItemsShow Left Unique ItemsShow Right Unique Items。这样列表中就只剩下相同的文件了。之后,选择EditSelect All,右键单击任意文件,然后单击DeleteRight。这将从右侧文件夹中删除重复项。

WinMerge 演示

答案2

可以通过命令行使用命令完成此操作forfiles

假设文件夹 A 位于c:\temp\Folder A,文件夹 B 位于c:\temp\Folder B

那么命令将是:

c:\>forfiles /p "c:\temp\Folder A" /c "cmd /c del c:\temp\Folder B\@file"

完成后,文件夹 B 中存在的所有文件都将被删除。请记住,如果文件夹 B 中有同名但内容不同的文件,它们仍会被删除。

可以将其扩展以适用于子文件夹中的文件夹,但出于对这变得不必要的复杂的担心,我决定不发布它。它需要 /s 和 @relpath 选项(以及进一步测试 xD)

答案3

您可以使用以下 PowerShell 脚本:

$folderA = 'C:\Users\Ben\test\a\' # Folder to remove cross-folder duplicates from
$folderB = 'C:\Users\Ben\test\b\' # Folder to keep the last remaining copies in
Get-ChildItem $folderB | ForEach-Object {
    $pathInA = $folderA + $_.Name
    If (Test-Path $pathInA) {Remove-Item $pathInA}
}

希望它相当不言自明。它查看文件夹 B 中的每个项目,检查文件夹 A 中是否有同名的项目,如果有,则删除文件夹 A 项目。请注意,\文件夹路径中的最后一个很重要。

单行版本:

gci 'C:\Users\Ben\test\b\' | % {del ('C:\Users\Ben\test\a\' + $_.Name) -EA 'SilentlyContinue'}

如果您不介意控制台中是否出现大量红色错误,您可以删除-EA 'SilentlyContinue'

将其保存为.ps1文件,例如dedupe.ps1。在运行 PowerShell 脚本之前,您需要启用它们的执行:

Set-ExecutionPolicy Unrestricted -Scope CurrentUser

.\dedupe.ps1然后,当您位于包含它的文件夹中时,您将能够调用它。

答案4

LPChip 的答案是更好的一个。

但是因为我已经开始学习 Python,所以我想,“哎呀,为什么不编写一个 Python 脚本来回答这个问题呢?”

安装 Python 和 Send2Trash

您需要先安装 Python 才能从命令行运行脚本。

然后安装发送至垃圾桶因此,被删除的文件不会无可挽回地消失,而是最终进入操作系统的垃圾箱:

pip install Send2Trash

创建脚本

创建一个新的文件,例如名称DeleteDuplicateInFolderA.py

将以下脚本复制到文件中。

#!/usr/bin/python

import sys
import os
from send2trash import send2trash


class DeleteDuplicateInFolderA(object):
    """Given two paths A and B, the application determines which files are in
       path A which are also in path B and then deletes the duplicates from
       path A.

       If the "dry run" flag is set to 'true', files are deleted. Otherwise
       they are only displayed but not deleted.
    """

    def __init__(self, path_A, path_B, is_dry_run=True):
        self._path_A = path_A
        self._path_B = path_B
        self._is_dry_run = is_dry_run

    def get_filenames_in_folder(self, folder_path):
        only_files = []
        for (dirpath, dirnames, filenames) in os.walk(folder_path):
            only_files.extend(filenames)
        return only_files

    def print_files(sel, heading, files):
        print(heading)
        if len(files) == 0:
            print("   none")
        else:
            for file in files:
                print("   {}".format(file))

    def delete_duplicates_in_folder_A(self):
        only_files_A = self.get_filenames_in_folder(self._path_A)
        only_files_B = self.get_filenames_in_folder(self._path_B)

        files_of_A_that_are_in_B = [file for file in only_files_A if file in only_files_B]

        self.print_files("Files in {}".format(self._path_A), only_files_A)
        self.print_files("Files in {}".format(self._path_B), only_files_B)

        if self._is_dry_run:
            self.print_files("These files would be deleted: ", [os.path.join(self._path_A, file) for file in files_of_A_that_are_in_B])
        else:
            print("Deleting files:")
            for filepath in [os.path.join(self._path_A, file) for file in files_of_A_that_are_in_B]:
                print("   {}".format(filepath))
                # os.remove(filepath)  # Use this line instead of the next if Send2Trash is not installed
                send2trash(filepath)

if __name__ == "__main__":
    if len(sys.argv) == 4:
        is_dry_run_argument = sys.argv[3]
        if not is_dry_run_argument == "--dryrun":
            println("The 3rd argument must be '--dryrun' or nothing.")
        else:
            app = DeleteDuplicateInFolderA(sys.argv[1], sys.argv[2], is_dry_run=True)
    else:
        app = DeleteDuplicateInFolderA(sys.argv[1], sys.argv[2], is_dry_run=False)
    app.delete_duplicates_in_folder_A()

用法

试运行模式,它会向您展示哪些文件将被删除,但实际上不会删除任何文件:

c:\temp> python .\DeleteDuplicateInFolderA.py c:\temp\test\A c:\temp\test\B --dryrun

文件删除模式,确实会删除文件,所以要小心:

c:\temp> python .\DeleteDuplicateInFolderA.py c:\temp\test\A c:\temp\test\B

空运行模式的输出

Files in C:\temp\A
  1.txt
  2.txt
Files in C:\temp\B
  2.txt
  3.txt
These files would be deleted:
  C:\temp\A\2.txt

文件删除模式输出

Files in C:\temp\A
  1.txt
  2.txt
Files in C:\temp\B
  2.txt
  3.txt
Deleting files:
  C:\temp\A\2.txt

单元测试

如果您想测试上述应用程序,请创建一个名为的文件DeleteDuplicateInFolderATest.py并将这些单元测试粘贴到其中:

import unittest
import os
import shutil
from DeleteDuplicateInFolderA import DeleteDuplicateInFolderA


class DeleteDuplicateInFolderATest(unittest.TestCase):

    def __init__(self, *args, **kwargs):
        super(DeleteDuplicateInFolderATest, self).__init__(*args, **kwargs)
        self._base_directory = r"c:\temp\test"
        self._path_A = self._base_directory + r"\A"
        self._path_B = self._base_directory + r"\B"

    def create_folder_and_create_some_files(self, path, filename_list):
        if os.path.exists(path):
            shutil.rmtree(path)
        os.makedirs(path)
        for filename in filename_list:
            open(os.path.join(path, filename), "w+").close()

    def setUp(self):
        # Create folders and files for testing
        self.create_folder_and_create_some_files(self._path_A, ["1.txt", "2.txt"])
        self.create_folder_and_create_some_files(self._path_B, ["2.txt", "3.txt"])

    def tearDown(self):
        for path in [self._path_A, self._path_B, self._base_directory]:
            if os.path.exists(path):
                shutil.rmtree(path)

    def test_duplicate_file_gets_deleted(self):
        # Arrange
        app = DeleteDuplicateInFolderA(self._path_A, self._path_B, is_dry_run=False)

        # Act
        app.delete_duplicates_in_folder_A()

        # Assert
        self.assertFalse(os.path.isfile(self._path_A + r"\2.txt"), "File 2.txt has not been deleted.")

    def test_duplicate_file_gets_not_deleted_in_mode_dryrun(self):
        # Arrange
        app = DeleteDuplicateInFolderA(self._path_A, self._path_B, is_dry_run=True)

        # Act
        app.delete_duplicates_in_folder_A()

        # Assert
        self.assertTrue(os.path.isfile(self._path_A + r"\2.txt"), "File 2.txt should not have been deleted in mode '--dryrun'")

def main():
    unittest.main()

if __name__ == '__main__':
    main()

相关内容