![查找并删除不同磁盘和目录中的重复文件](https://linux22.com/image/1532866/%E6%9F%A5%E6%89%BE%E5%B9%B6%E5%88%A0%E9%99%A4%E4%B8%8D%E5%90%8C%E7%A3%81%E7%9B%98%E5%92%8C%E7%9B%AE%E5%BD%95%E4%B8%AD%E7%9A%84%E9%87%8D%E5%A4%8D%E6%96%87%E4%BB%B6.png)
我有数十万个文件分布在许多外部磁盘和计算机磁盘中,其中许多文件都是重复的。这种混乱是我自己为了安全建议而创建副本造成的。我不时更改组织的目录结构,但没有在有副本的其他地方复制。
现在,我有一个巨大的磁盘,里面几乎存储了我真正需要的所有内容的备份和镜像。
我想要一种方法来从大磁盘中已经存在的所有分布式磁盘中删除所有内容。
让我展示一下这个场景:
旧磁盘1:
/code/{manystructures}/{manyfiles}
/docs/{manystructures}/{manyfiles}
旧磁盘2:
/dev/{another_structures}/{same_files_different_names}
/documents/{another_structures}/{same_files_different_names}
新巨盘:
/home/username/code/{new_strutucture}/{new_files}
/home/username/documents/{new_strutucture}/{new_files}
有人知道一个工具或方法来做类似“在 OldDisk1 上找到所有已经在 NewHugeDisk 中的文件并删除”的事情吗?
我研究了许多工具(Windows、Mac 和 Linux,因为我在这两个软件上都遇到了这个问题),免费的和付费的,但都没有成功。
我的想法是编写代码来实现这一点,但我不是开发人员。我可以编写一些小而简单的代码,但我认为这种代码对我来说太复杂了。
我将非常感激任何有关此事的帮助或想法。
答案1
假设你可以使用 Windows 作为整个过程的操作系统,并且你不喜欢免费重复文件查找器(从未尝试过,但发现它提到这里),您可以使用 PowerShell 以相对较少的努力实现您想要的目标。注意:我不是 PowerShell 的真正专家,所以我很确定有人可以改进我的代码。
只需打开 Powershell ISE(或者,如果您没有,请使用记事本),将以下代码复制并粘贴到其中,然后将生成的文件保存为 *.ps1。您还必须将$oldpath
和 的$newpath
值更改为您的目录 - 只需将您的路径放在引号之间即可。
# Search-and-Destroy-script
# Get all files of both code-directories:
$oldpath = "Disk1:\code"
$newpath = "DiskNew:\code"
$files_old = Get-ChildItem -Path $oldpath -Recurse -File
$files_new = Get-ChildItem -Path $newpath -Recurse -File
for($i=0; $i -lt $files_old.length; $i++){
$j=0
while($true){
# if last edit time is the same and file-size is the same...
if($($files_old[$i]).length -eq $($files_new[$j]).length -and $($files_old[$i]).lastWriteTime -eq $($files_new[$j]).lastWriteTime){
# Get File-Hashes for those files (SHA1 should be enough)
$files_old_hash = Get-FileHash -Path $($files_old[$i]).FullName -Algorithm SHA1 | ForEach-Object {$_.Hash}
$files_new_hash = Get-FileHash -Path $($files_new[$j]).FullName -Algorithm SHA1 | ForEach-Object {$_.Hash}
# if hashes also are the same...
if($files_old_hash -eq $files_new_hash){
# remove the old file (-Confirm can be removed so you don't have to approve for every file)
# if you want to check the files before deletion, you could also just rename them (here we're adding the suffix ".DUPLICATE"
# Rename-Item -Path $($files_old[$i]).FullName -NewName "$($files_old[$i]).Name.DUPLICATE"
Remove-Item -Path $($files_old[$i]).FullName -Confirm
Write-Host "DELETING`t$($files_old[$i]).FullName" -ForegroundColor Red
break
}
# if files aren't the same...
}else{
# if old_file is compared to all new_files, check next old file
if($j -ge $files_new.length){
break
}
}
$j++
}
}
然后启动脚本(例如,通过右键单击) - 如果失败,请确保已ExecutionPolicy
设置(https://superuser.com/a/106363/703240)。
我使用几乎相同的脚本来检查已复制的文件(但可能更改了名称)。此代码假设只有文件的名称不同,而内容相同。即使将文件复制到新路径后,上次编辑时间通常也保持不变 - 与创建时间不同。如果内容不同,我的解决方案将严重失败 - 您可以使用文件的不同唯一属性(但使用哪个?)或声明例如只有比新文件更小或更旧的文件(再次考虑编辑时间)才应被删除。
脚本的作用:
- 获取指定文件夹(及其子文件夹)中的所有文件
- 获取第一个旧文件(由 $i 指定)...
- 将其最后编辑时间和文件大小与第一个新文件(由 $j 指定)进行比较……
- ...如果它们相等,它会计算文件哈希以确保它绝对是同一个文件(可以说,这对于你的目标来说可能有点太费力了)
- 如果哈希值相等,则删除旧文件(并且它会在终端中写入哪个文件),然后从 2 重新开始处理下一个旧文件......
- 如果哈希值不相等(或者最后编辑时间不相等或文件大小不相等)它会从 3 重新开始处理下一个新文件。
答案2
林特是一个命令行实用程序,其中包含可执行您想要的操作的选项。它可在 Linux 和 macOS 上运行。您需要的命令是:
$ rmlint --progress \
--must-match-tagged --keep-all-tagged \
/mnt/OldDisk1 /mnt/OldDisk2 // /mnt/NewHugeDisk
这将找到您想要的重复项。它不会直接删除它们,而是创建一个 shell 脚本 (./rmlint.sh),您可以查看该脚本,也可以选择编辑它,然后执行它以执行所需的删除操作。
“--progress”选项为您提供了一个不错的进度指示器。“//”将“未标记”路径与“标记”路径分开;“//”后面的路径被视为“标记”。“--must-match-tagged --keep-all-tagged”表示仅在未标记路径中查找在标记路径中有副本的文件。
您还可以使用选项的短格式来缩短该命令:
rmlint -g -m -k /mnt/OldDisk1 /mnt/OldDisk2 // /mnt/NewHugeDisk
答案3
您是否尝试过使用第三方重复数据删除软件?
我试过云莓重复数据删除而且它确实很有效:
- 它有自己的重复数据删除机制来消除重复数据,从而节省大量的存储空间。
- 此类工具的另一个优点是它们更可靠并且具有专门的资源管理技术。