別のフォルダーにあるフォルダーからファイルを削除する方法はありますか?


21

以下を含むフォルダー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の方法か、これを行うことができるいくつかのソフトウェアのいずれかを好むだろう

ありがとう!


4
内容的に同じファイルであることをどのように知っていますか?ファイル名だけに基づいて、ファイルを盲目的に重複しているとみなすシナリオを想像することはできません。
rory.ap

@roryap OPはフォルダー1からフォルダー2にファイルをコピーしたため、この質問が発生したと思います。しかし、あなたは正しいです、あなたが知ることができない満足してください。
LPChip

13
馬鹿げた質問です...「カット」と「ペースト」を使用しないのはなぜですか?
-DaMachk

@DaMachkは、ネットワークドライブまたはリムーバブルメディアを使用している場合、copy-> verify-> clean-upが妥当なルートです。ファイルが何らかのプロセスで使用されている場合、コピーでテストすることをお勧めします(たとえば、入力ファイルを破壊する独自のコードのバグの場合、Pythonデータ分析用のファイルでこれを行います)。以前のように必要ではありませんが、古い習慣などすべて。あるいは、OPがカットではなくコピーを誤ってクリックした可能性があります
クリスH

回答:


35

WinMergeと呼ばれるフリーソフトウェアがあります。このソフトウェアを使用して、重複を一致させることができます。最初に、File→を使用してOpen、両方のディレクトリを選択します。左側に残しておきたいファイルがあるフォルダーと、右側に残さないフォルダーを選択します。次に、に行きView、そして選択解除Show Different ItemsShow Left Unique ItemsShow Right Unique Items。これにより、リストに同一のファイルのみが残ります。その後、Edit→を選択し、Select All任意のファイルを右クリックして、Delete→ をクリックしますRight。これにより、右側のフォルダーから重複が削除されます。

WinMergeのデモ


この方法の利点は、これが重要な場合、ファイルが内容的に類似していないかどうかを検出できることです。WinMergeは、重要なすべての要因を1つと比較できます。

25

これは、次のコマンドを使用してコマンドラインから実行できます。 forfiles

にフォルダーAがあり、c:\temp\Folder AフォルダーBがフォルダーBにあるとしますc:\temp\Folder B

コマンドは次のようになります。

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

これが完了すると、フォルダーBにはフォルダーAに存在するすべてのファイルが削除されます。フォルダーBに同じ名前のファイルがあり、同じコンテンツではない場合、それらは削除されます。

これをサブフォルダー内のフォルダーでも機能するように拡張することは可能ですが、これが不必要に複雑になるのを恐れて、私はそれを投稿しないことにしました。/ sおよび@relpathオプションが必要です(さらにxDをテストします)


11

次の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のアイテムを削除します。\フォルダパスの最後が重要であることに注意してください。

1行バージョン:

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

rsync

rsyncディレクトリを同期するために使用されるプログラムです。あなたが持っている多くの(本当に多くの)オプションから、自己説明--ignore-non-existing--remove-source-filesあり--recursiveます。

できるよ

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

ディレクトリA(4)および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

LPChipの答えはより良いものです。

しかし、Pythonを学び始めたので、「一体、この質問の答えとしてPythonスクリプトを書いてみませんか?」

PythonとSend2Trashをインストールする

コマンドラインからスクリプトを実行する前に、Pythonをインストールする必要があります。

次に、Send2Trashをインストールして、削除されたファイルが回復不能にならないようにし、OSのゴミ箱に入れます。

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

このスクリプトが「地獄のようにugい」理由を教えてください。私はそれをただ読んで、あなたがしていることは非常に明確です。CodeReview.SEに貼り付けて、好ましくないものを知りたくなります。
user1717828

ファイルの内容が同じかどうかを確認するためにmd5sumを追加するのは良いオプションです。また、削除する代わりにOSのゴミ箱メカニズムを使用します
ロレスク

@ user1717828:コードを再構築し、そのコメントを削除し、CodeReview.SEにコード投稿するように提案しました
レルンクルブ

@lolesque:Send2Trashパート:完了。アイデアをありがとう!
レルンクルブ

1
@barlop、私はコメントではなく、元の投稿に返信していました。
user1717828

1

bashを使用する

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

ファイルが存在するかどうか、またはファイル名が安全かどうかを確認することで、より安全になります。ただし、これを実行したいだけで、おかしな名前のファイルが入っていないことを前提としています。folderBこれは、それを実行するための迅速で汚い方法です。(Win10 + bashを実行していない場合は、gitに付属のbashエミュレーターを使用できます)


ディレクトリを見つけたらチェックを追加する必要があるかもしれません...
Hastur

1

Total CommanderのようなNCスタイルのプログラムには、両方のタブで他のタブとは異なるファイルを選択するディレクトリ差分コマンドがあります。このコマンドtabを大きなディレクトリ(B)に呼び出し、選択を反転し*て削除します。これには、(何らかの理由で)変更された可能性があり、名前が一致しているファイルとは異なるファイルを削除しないという利点があります。同じディレクトリdiffコマンドを使用して、削除後にこれらを見つけることができます。

私は90年代に立ち往生していると思います...しかし、私は本当にエレガントなものを見ていません:-)これまでのところ、これはわずか5回のキーストロークとスクリプト/コマンドラインをまったく必要としない唯一の答えです。


1

フォルダーAからフォルダーBにファイルをコピーして貼り付けたとします。

フォルダーBにあるフォルダーAからすべてのファイルを削除する方法はありますか?それぞれを手動で選択して削除するか、コピー&ペーストの直後にCtrl-Zを押す

Windowsメソッド

常にある場所から別の場所にファイルをコピーする必要があり、その後、正常にコピーされたファイルが元のソースの場所からも削除されることを確認する場合、以下は、タスク全体を自動化するために使用できるバッチスクリプトソリューションです各実行をクリックするだけです。

  • 必要に応じてSourceDirとを適切に設定しDestDirてください。

  • また、以下のスクリプトの一部では、必要に応じてファイル名()またはファイル拡張子()("%SourceDir%\*.*") DO*.*値をより明示的に変更することができます。File A.txt*.wav


@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

さらなるリソース

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.