Gibt es eine Möglichkeit, Dateien aus einem Ordner zu entfernen, der sich in einem anderen Ordner befindet?


21

Angenommen, ich kopiere und füge Dateien aus Ordner A ein. Dazu gehören:

Ordner A:

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

in Ordner B, der nach dem Update Folgendes enthält:

Ordner B:

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

Gibt es eine Möglichkeit, alle Dateien aus Ordner A zu löschen, die sich in Ordner B befinden (gekennzeichnet mit einem *)? Neben der manuellen Auswahl und dem Löschen jeder Datei oder der Strg-Z-Taste direkt nach dem Kopieren-Einfügen

Ich würde entweder eine Windows-Methode oder eine Software bevorzugen, die dies tun könnte

Vielen Dank!


4
Woher weißt du, dass sie inhaltlich die gleichen Dateien sind? Ich kann mir kein Szenario vorstellen, in dem Sie eine Datei blind als Duplikat betrachten möchten, nur basierend auf dem Dateinamen.
rory.ap

@roryap Ich denke, diese Frage entstand, weil OP die Dateien von Ordner 1 in Ordner 2 kopierte, alle ersetzte und jetzt denkt, hmm, das war ein Fehler, aber merkt, dass am nächsten Tag, also Rückgängigmachen nicht möglich ist. Aber du hast recht, zufrieden, du kannst es nicht wissen.
LPChip

13
Nur eine blöde Frage ... Warum nicht "Ausschneiden" und "Einfügen" verwenden?
DaMachk

@DaMachk Wenn Sie mit Netzwerklaufwerken oder Wechseldatenträgern arbeiten, ist Kopieren-> Überprüfen-> Bereinigen eine sinnvolle Methode. Wenn die Dateien von einem bestimmten Prozess verwendet werden, ist es möglicherweise eine gute Idee, sie auf einer Kopie zu testen (ich mache dies mit Dateien für die Python-Datenanalyse, falls Fehler in meinem eigenen Code die Eingabedatei beschädigen (zum Beispiel). Möglicherweise Nicht mehr so ​​notwendig wie früher, sondern alte Gewohnheiten und so weiter. Alternativ könnte das OP eine Kopie falsch angeklickt haben, anstatt sie auszuschneiden.
Chris H

Antworten:


35

Es gibt freie Software namens WinMerge . Mit dieser Software können Sie Duplikate abgleichen. Verwenden Sie zunächst FileOpenund wählen Sie beide Verzeichnisse aus. Der Ordner mit den Dateien, die Sie behalten möchten, befindet sich links und die nicht rechts. Dann gehen Sie zu View, und Abwahl Show Different Items, Show Left Unique Itemsund Show Right Unique Items. Dadurch verbleiben nur die identischen Dateien in der Liste. Wählen Sie anschließend EditSelect All, klicken Sie mit der rechten Maustaste auf eine beliebige Datei und klicken Sie auf DeleteRight. Dadurch werden die Duplikate aus dem Ordner auf der rechten Seite gelöscht.

Demo von WinMerge


Der Vorteil dieser Methode ist, dass sie erkennen kann, ob die Dateien inhaltlich nicht ähnlich sind, wenn dies wichtig ist. WinMerge kann alle wichtigen Faktoren mit einem vergleichen.

25

Dies kann mit dem Befehl über die Befehlszeile erfolgen forfiles

Nehmen wir an, Sie haben Ordner A c:\temp\Folder Aund Ordner Bc:\temp\Folder B

Der Befehl wäre dann:

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

Anschließend werden in Ordner B alle Dateien entfernt, die in Ordner A vorhanden sind. Beachten Sie, dass in Ordner B Dateien mit demselben Namen, aber nicht demselben Inhalt weiterhin gelöscht werden.

Es ist möglich, dies zu erweitern, um auch mit Ordnern in Unterordnern zu arbeiten, aber aus Angst, dass dies unnötig kompliziert wird, habe ich mich dagegen entschieden, es zu veröffentlichen. Hierfür sind die Optionen / s und @relpath erforderlich (und weitere Tests von xD).


11

Sie können dieses PowerShell-Skript verwenden:

$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}
}

Hoffentlich ist es ziemlich selbsterklärend. Es überprüft jedes Element in Ordner B, ob es in Ordner A ein Element mit demselben Namen gibt, und entfernt in diesem Fall das Element in Ordner A. Beachten Sie, dass das Finale \in den Ordnerpfaden wichtig ist.

Einzeilige Version:

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

Wenn es Ihnen egal ist, ob in der Konsole eine Flut roter Fehler angezeigt wird, können Sie die entfernen -EA 'SilentlyContinue'.

Speichern Sie es als .ps1Datei, z dedupe.ps1. Bevor Sie PowerShell-Skripts ausführen können, müssen Sie deren Ausführung aktivieren:

Set-ExecutionPolicy Unrestricted -Scope CurrentUser

Dann können Sie es mit aufrufen, .\dedupe.ps1wenn Sie sich in dem Ordner befinden, der es enthält.


4

rsync

rsyncist ein Programm zum Synchronisieren von Verzeichnissen. Aus den vielen (wirklich viele) Optionen , die Sie haben , gibt es die selbsterklärend --ignore-non-existing, --remove-source-filesund --recursive.

Du kannst tun

rsync -avr --ignore-non-existing --recursive --remove-source-files   B/ A -v

Nehmen wir an, Sie haben die Dateien im Verzeichnis A (4) und B (4 + 2).

A       B
├── a   ├── a
├── b   ├── b
├── c   ├── c
└── d   ├── d
        ├── e
        └── f     # Before


A       B
├── a   ├── e
├── b   └── f
├── c   
└── d             # After

4

Die Antwort von LPChip ist die bessere.

Aber weil ich angefangen habe, Python zu lernen, dachte ich: "Mist, warum schreibst du nicht ein Python-Skript als Antwort auf diese Frage?"

Installieren Sie Python und Send2Trash

Sie müssen Python installieren, bevor Sie das Skript über die Befehlszeile ausführen können.

Installieren Sie dann Send2Trash, damit die gelöschten Dateien nicht unwiederbringlich gelöscht werden, sondern im Papierkorb des Betriebssystems landen:

pip install Send2Trash

Skript erstellen

Erstellen Sie eine neue Datei mit beispielsweise dem Namen DeleteDuplicateInFolderA.py

Kopieren Sie das folgende Skript in die Datei.

#!/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()

Verwendung

Trockenlaufmodus, in dem angezeigt wird, welche Dateien gelöscht würden, ohne dass tatsächlich Dateien gelöscht würden:

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

Dateilöschmodus, der tatsächlich Dateien löscht, also seien Sie vorsichtig:

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

Ausgabe des Trockenlaufmodus

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

Ausgabe des Dateilöschmodus

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

Gerätetest

Wenn Sie die obige Anwendung testen möchten, erstellen Sie eine Datei mit dem Namen DeleteDuplicateInFolderATest.pyund fügen Sie diese Unittests ein:

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()

Können Sie mir sagen, warum dieses Skript "hässlich wie die Hölle" ist? Ich habe es gerade durchgelesen und was Sie tun, ist kristallklar. Ich bin fast versucht, es in CodeReview.SE einzufügen, um zu erfahren, was nicht bevorzugt wird.
user1717828

Eine MD5-Summe hinzuzufügen, um zu prüfen, ob der Inhalt der Dateien identisch ist, wäre eine gute Option. Verwenden Sie auch den OS-Papierkorbmechanismus, anstatt ihn zu entfernen.
Lolesque

@ user1717828: Ich habe den Code umstrukturiert, diesen Kommentar gelöscht und Ihren Vorschlag angenommen, den Code auf CodeReview.SE zu veröffentlichen .
Lernkurve

@ Lolesque: Send2Trash Teil: fertig. Danke für die Idee!
Lernkurve

1
@barlop, ich habe auf den ursprünglichen Beitrag geantwortet, kein Kommentar.
user1717828

1

Bash benutzen

for f in $(ls /path/to/folderB/); do 
    rm -rf /path/to/folderA/$f
done

Sicher können Sie sicherer sein, indem Sie prüfen, ob die Datei vorhanden ist oder ob der Dateiname sicher ist. Angenommen, Sie möchten dies nur erledigen und haben keine lächerlich benannten Dateien darin folderB- dies ist eine schnelle und schmutzige Möglichkeit, dies zu erledigen. (und Sie können den mit git gelieferten Bash-Emulator verwenden , wenn Sie Win10 + bash nicht ausführen)


Vielleicht müssen Sie eine Überprüfung hinzufügen, wenn Sie Verzeichnisse finden ...
Hastur

1

Jedes NC-ähnliche Programm wie Total Commander verfügt über einen Verzeichnisunterschiedsbefehl, mit dem Dateien auf beiden Registerkarten ausgewählt werden, die sich von den anderen Registerkarten unterscheiden. Rufen Sie diesen Befehl auf, tabum das größere Verzeichnis (B) zu öffnen, Auswahl umzukehren *und zu löschen. Dies hat den Vorteil, dass Dateien nicht gelöscht werden, die sich (irgendwie) geändert haben und nicht gleich sind, obwohl sie im Namen übereinstimmen. Sie können denselben Befehl directory diff verwenden, um diese nach dem Löschen zu suchen.

Ich schätze, ich stecke in den Neunzigern fest ... aber ich habe seitdem nichts Eleganteres mehr gesehen :-) Bisher ist dies die einzige Antwort, die nur 5 Tastatureingaben und überhaupt kein Scripting / keine Befehlszeile erfordert.


1

Angenommen, ich kopiere und füge Dateien aus Ordner A in Ordner B ein.

Gibt es eine Möglichkeit, alle Dateien aus Ordner A zu löschen, die sich in Ordner B befinden? Neben der manuellen Auswahl und dem Löschen jeder Datei oder der Strg-Z-Taste direkt nach dem Kopieren-Einfügen

Windows-Methode

Wenn Sie immer Dateien von einem Speicherort an einen anderen kopieren und anschließend sicherstellen müssen, dass die erfolgreich kopierten Dateien auch vom ursprünglichen Quellspeicherort gelöscht werden, finden Sie nachfolgend eine Batch-Skript-Lösung, mit der Sie die gesamte Aufgabe mit nur einem automatisieren können Klicken Sie einfach auf jeden Lauf.

  • Stellen Sie sicher, dass Sie die SourceDirund die DestDirVariablen entsprechend Ihren Anforderungen einstellen .

  • Darüber hinaus können Sie im folgenden Teil des Skripts ("%SourceDir%\*.*") DOden *.*Wert einfach so ändern , dass er für Dateinamen ( File A.txt) oder Dateierweiterungen ( *.wav) nach Bedarf expliziter wird .


@ECHO ON
SET SourceDir=C:\Users\User\Desktop\Source
SET DestDir=C:\Users\User\Desktop\Dest

FOR %%A IN ("%SourceDir%\*.*") DO XCOPY /F /Y "%%~A" "%DestDir%\" && DEL /Q /F "%%~A"
GOTO EOF

Weitere Ressourcen

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.