フォルダ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メソッドまたはいくつかのソフトウェアを好むでしょう
ありがとう!
WinMerge と呼ばれる無料のソフトウェアがあります。このソフトウェアを使用して、重複を一致させることができます。最初に、File
→Open
を使用し、両方のディレクトリを選択します。左側に、残しておきたいファイルを含むフォルダを、右側には残さないようにします。次に、View
に移動し、Show Different Items
、Show Left Unique Items
、およびShow Right Unique Items
の選択を解除します。これにより、同じファイルがリストに残ります。その後、Edit
→Select All
を選択し、任意のファイルを右クリックして、Delete
→Right
をクリックします。これにより、右側のフォルダから重複が削除されます。
これは、コマンド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にはフォルダーAに存在するすべてのファイルが削除されます。フォルダーBに同じ名前のファイルがあり、同じ内容ではない場合、それらのファイルは削除されることに注意してください。
これを拡張してサブフォルダー内のフォルダーを操作することも可能ですが、これが不必要に複雑になるのを恐れて、投稿しないことにしました。/sおよび@relpathオプションが必要になります(さらにxDをテストします)
次の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
でそれを呼び出すことができます。
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
LPChipの回答 の方が適しています。
しかし、私はPythonを学び始めたので、「では、Pythonスクリプトをこの質問への回答として書いてみませんか?」
コマンドラインからスクリプトを実行する前に、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()
Total CommanderのようなNCスタイルのプログラムには、他のタブとは異なる両方のタブでファイルを選択するディレクトリ差分コマンドがあります。このコマンドtab
を大きなディレクトリ(B)に呼び出し、*
を使用して選択を反転して削除します。これには、(何らかの形で)変更された可能性があり、名前が一致しても同じではないファイルを削除しないという利点があります。同じディレクトリのdiffコマンドを使用して、削除後にこれらを見つけることができます。
私は90年代に行き詰まっていると思います...しかし、これ以上エレガントなものは見たことがありません。
bashを使用する
for f in $(ls /path/to/folderB/); do
rm -rf /path/to/folderA/$f
done
確かに、ファイルが存在するかどうか、またはファイル名が安全かどうかを確認することで、より安全になる可能性があります。しかし、これを実行したいだけで、folderB
にばかばかしい名前のファイルがない場合を想定しています。これは、すばやく簡単に実行できる方法です。 (Win10 + bashを実行していない場合は、 git に付属のbashエミュレータを使用できます)
フォルダAからフォルダBにファイルをコピーアンドペーストするとします
フォルダBにあるすべてのファイルをフォルダAから削除する方法はありますか?それぞれを手動で選択して削除するほか、コピーと貼り付けの直後にCtrl + Zを押します
ある場所から別の場所に常にファイルをコピーする必要があり、その後、正常にコピーされたファイルが元のソースの場所からも削除されることを確認する必要がある場合は、以下のバッチスクリプトソリューションを使用して、タスク全体を自動化できます。各実行をクリックするだけです。
必要に応じて、必ず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