Удаление одинаковых файлов по размеру
Добрый день, нужен батник который сравнивал и удалял одинаковые по размеру файлы в одной папке (и оставлял только один).
Сторонние программы не хочу использовать, нужно именно bat.
|
Код:
@Echo off
set Size=66
set Files=C:\help\*.*
rem Если размер должен быть равным или меньшим Size, то EQU заменить на LEQ
for %%L in (%Files%) do if /i %%~zL EQU %Size% del /f "%%L"
|
Цитата:
Цитата Arsenik77
Сторонние программы не хочу использовать, нужно именно bat. »
|
Как насчёт скрипта VBScript?
Код:
Option Explicit
Dim objFSO
Dim strFolder
Dim objFile
Dim objDictionary
Dim elem
If WScript.Arguments.Count = 1 Then
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
strFolder = WScript.Arguments.Item(0)
If objFSO.FolderExists(strFolder) Then
Set objDictionary = WScript.CreateObject("Scripting.Dictionary")
For Each objFile In objFSO.GetFolder(strFolder).Files
If objDictionary.Exists(objFile.Size) Then
If objDictionary.Item(objFile.Size) <> "" Then
objFSO.DeleteFile objDictionary.Item(objFile.Size), True
objDictionary.Item(objFile.Size) = ""
End If
objFSO.DeleteFile objFile.Path, True
Else
objDictionary.Add objFile.Size, objFile.Path
End If
Next
objDictionary.RemoveAll
Set objDictionary = Nothing
Else
WScript.Echo "Folder [" & strFolder & "] not found."
End If
Set objFSO = Nothing
Else
WScript.Echo "Usage: " & WScript.ScriptName & " <folder>"
End If
WScript.Quit 0
Путь к папке указываем аргументом скрипта.
|
PowerShell:
Код:
param (
[string]$Folder = "E:\Песочница\0061\*"
)
Get-ChildItem -Path $Folder | `
Where-Object -FilterScript { -not $_.PSIsContainer } | `
Group-Object -Property Length | `
Where-Object -FilterScript { $_.Count -gt 1 } | `
ForEach-Object -Process {
Remove-Item $_.Group
}
|
root221, мне надо чтоб файлы сравнивались между собой (по размеру), а не по конкретному размеру.
Я, в скриптах нуль.
Iska, скрипт полностью удаляет все файлы в папке.
|
Arsenik77,
Еще вариант:
Код:
@echo off
setlocal enabledelayedexpansion
pushd "c:\test" || goto:eof
for /f "tokens=*" %%i in ('dir /b /a-d') do call:1 "%%i"
for /f "tokens=2 delims==" %%i in ('set todel_') do echo del %%i %%~zi
popd
goto:eof
:1
if not defined file_%~z1 (
set "file_%~z1=%1"
) else (
echo del !file_%~z1! %~z1
set "file_%~z1=%1"
set "todel_%~z1=%1"
)
То что красным удалишь после проверки, зеленым исправишь на своё
|
Foreigner, не работает, написал "Непредвиденное появление: .jpg" (сравниваю jpg)
|
Задача не очень четко поставлена. Вот решение, удаляем все одинаковые по размеру файлы.
Код:
@Echo Off
Set Otkuda=D:\Delete
Set S1=-1
FOR /F "usebackq delims=" %%f IN (`Dir /B /A:-D /O:SN "%Otkuda%\"`) DO Call :DelSize "%Otkuda%\%%f"
GoTo :Eof
:DelSize
Set S2=%~z1
If %S1% NEQ %S2% (
Set S1=%S2%
Set N1=%1
) Else (
Del %1
If Exist %N1% Del %N1%
)
Если надо по одному файлу из тех, у которых размер одинаков, оставить, то строку
If Exist %N1% Del %N1%
следует удалить.
|
Цитата:
Цитата Arsenik77
"Непредвиденное появление: .jpg" (сравниваю jpg) »
|
вы так одинаковые изображения хотите удалить?
|
Arsenik77,
Мой батник удаляет все одинаковые по размеру файлы, независимо от расширения. Если есть например три файла размером 123 и семь файлов размером 321, то он их всех удалит, но оставит файл размером 124, т.к. он один такого размера. В батнике надо указать только папку, в которой сравнивать.
Цитата:
Цитата Arsenik77
Добрый день, нужен батник который удалял одинаковые по размеру файлы в одной папке. »
|
|
root221, Iska, Foreigner, megaloman, - СПАСИБО!
megaloman - работает.
|
megaloman, поторопился немного, bat-к работает, но как-то выборочно. Проверил на 5000 файлов в папке, батник удаляет, но не всЁ.
Примерно разобрался в чем дело, на файлах где есть в арабские (китайские) или другие не типичные символы батник затыкаеться.
типа XXXXXXXXXXXXX_Штукатурка.jpg
Нужно чтоб батник переименовывал их, во что нибудь типа XXXXXXXXXXXXX_yyyyy.jpg, где XXXXXXXXXXXXX - важные символы, yyyyy неважно.
Батник будет проверять по 100-200 тыс.файлов.
|
Цитата:
Цитата Arsenik77
Iska, скрипт полностью удаляет все файлы в папке. »
|
Arsenik77, какой скрипт из двух? У меня работают оба варианта.
Если Вам нужно искать и удалять дубликаты — то это совсем другой разговор, например, «CloneSpy» или «Duplicate Files Finder», або что-то своё — в зависимости от конкретной задачи и условий применения.
|
Iska, работает VBScript, PowerShell не понял как запускать.
Но только надо по одному файлу из тех, у которых размер одинаков, оставить.
Скрипт также работает с "трудными" именами файлов.
|
Попробуйте вариант решения, но при таком большом числе файлов не уверен, как сработает сортировка в Dir. Я попробовал на 50000 файлов, но они небольшого размера
Код:
@Echo Off
Set Otkuda=E:\dddddddd
Set S1=-1
FOR /F "usebackq delims=" %%f IN (`Dir /B /A:-D /O:S "%Otkuda%\"`) DO Call :DelSize "%Otkuda%\%%f"
GoTo :Eof
:DelSize
Set S2=%~z1
If %S1% NEQ %S2% (
Set S1=%S2%
) Else (
Del %1
)
|
megaloman, работает с нормальным именами файлов, затык идет на таких именах у файло⠨тукатурка.jpg
|
Arsenik77,
Попробуй такой вариант, правда на большом кол-ве файлов не проверял:
Код:
@echo off
setlocal
pushd "c:\test\folder" || goto:eof
for /f "tokens=*" %%i in ('dir /b /a-d') do call:del "%%~fi"
popd
goto:eof
:del
set "file=%~1"
2>nul 1>nul (
wmic datafile where "path='\\test\\folder\\' and filesize='%~z1' and not name='%file:\=\\%'" call delete
)
|
Батник затыкается на не правильных именах файлов, типа :
читать дальше »
16_21217_26+PE%C3%87AS+PRONTAS.JPG.jpg
12809_Гостиная_3.jpg.jpg
12810_Штукатурка_1.jpg.jpg
12811_Штукатурка_2.jpg.jpg
Либо эти файлы (с кривыми именами) надо удалять, либо как-то переименовывать.
Задачу считаю решенной, спасибо megaloman
|
В принципе, у меня сработали и пакетный файл Foreigner'а, и пакетный файл megaloman'а.
Цитата:
Цитата Arsenik77
Но только надо по одному файлу из тех, у которых размер одинаков, оставить. »
|
Ясно. Поскольку изначально в условиях задачи было сказано, что:
Цитата:
Цитата Arsenik77
удалял одинаковые по размеру файлы в одной папке »
|
то, я хоть и удивился, но сделал именно так, как было сказано :). Причём, коллега megaloman оказался проницательнее — не только удивился, но и усомнился (и, как выяснилось, оказался прав).
Тогда ещё проще (хоть уже и нет необходимости, но приведу код):
Код:
Option Explicit
Dim objFSO
Dim strFolder
Dim objFile
Dim objDictionary
Dim elem
If WScript.Arguments.Count = 1 Then
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
strFolder = WScript.Arguments.Item(0)
If objFSO.FolderExists(strFolder) Then
Set objDictionary = WScript.CreateObject("Scripting.Dictionary")
For Each objFile In objFSO.GetFolder(strFolder).Files
If objDictionary.Exists(objFile.Size) Then
objFSO.DeleteFile objFile.Path, True
Else
objDictionary.Add objFile.Size, objFile.Path
End If
Next
objDictionary.RemoveAll
Set objDictionary = Nothing
Else
WScript.Echo "Folder [" & strFolder & "] not found."
End If
Set objFSO = Nothing
Else
WScript.Echo "Usage: " & WScript.ScriptName & " <folder>"
End If
WScript.Quit 0
и примерно так (уверен, что подобрал не самый оптимальный вариант):
Код:
param (
[string]$Folder = "E:\Песочница\0061\*"
)
Get-ChildItem -Path $Folder | `
Where-Object -FilterScript { -not $_.PSIsContainer } | `
Group-Object -Property Length | `
Where-Object -FilterScript { $_.Count -gt 1 } | `
ForEach-Object -Process {
$_.Group | Select-Object -Skip 1 | Remove-Item -Force
}
|
Цитата:
Цитата Arsenik77
Батник затыкается на не правильных именах файлов »
|
ну это не проблема, вот два различных решения:
Код:
@(
pushd "C:\TEST"
for /f "delims=" %%f in ('dir/b/a-d/os') do @(
if defined $fz (set/a "$fc=$fz-%%~zf"
call set "$fc=%%$fc:0=%%"
if not defined $fc del "%%f")
set "$fz=%%~zf"))
Код:
@(
pushd "C:\TEST"
for /f "delims=" %%f in ('dir/b/a-d/os') do @(
if defined $fz (SetLocal EnableDelayedExpansion
if !$fz! equ %%~zf del "%%f"
EndLocal)
set "$fz=%%~zf"))
|
Iska, А можете сделать log файл, сколько файлов было удалено??
Скрипт отлично работает, большое спасибо!!
|
Цитата:
Цитата Arsenik77
Iska, А можете сделать log файл, сколько файлов было удалено?? »
|
Попробуйте так:
Код:
Option Explicit
' IOMode Enum
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
' Format Enum
Const TristateUseDefault = -2
Const TristateTrue = -1
Const TristateFalse = 0
Dim objFSO
Dim strFolder
Dim objFile
Dim objDictionary
Dim elem
Dim objTS
If WScript.Arguments.Count = 1 Then
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
strFolder = WScript.Arguments.Item(0)
If objFSO.FolderExists(strFolder) Then
Set objTS = objFSO.OpenTextFile( _
objFSO.BuildPath( _
objFSO.GetParentFolderName(WScript.ScriptFullName), _
objFSO.GetBaseName(WScript.ScriptFullName) & ".log" _
), ForAppending, True, TristateTrue)
objTS.WriteLine
objTS.WriteLine FormatDateTime(Now())
objTS.WriteLine
Set objDictionary = WScript.CreateObject("Scripting.Dictionary")
For Each objFile In objFSO.GetFolder(strFolder).Files
If objDictionary.Exists(objFile.Size) Then
objTS.WriteLine objFile.Path
objFSO.DeleteFile objFile.Path, True
Else
objDictionary.Add objFile.Size, objFile.Path
End If
Next
objDictionary.RemoveAll
Set objDictionary = Nothing
objTS.Close
Set objTS = Nothing
Else
WScript.Echo "Folder [" & strFolder & "] not found."
End If
Set objFSO = Nothing
Else
WScript.Echo "Usage: " & WScript.ScriptName & " <folder>"
End If
WScript.Quit 0
Лог-файл будет создан в той же папке [сие, конечно, в корне неправильно] и под тем же именем, что и скрипт, но с расширением «.log».
P.S. Или имена Вам не важны, а нужно именно количество удалённых файлов?
|
Цитата:
Цитата Iska
нужно именно количество удалённых файлов »
|
правильно мыслите,
Цитата:
Цитата Iska
сие, конечно, в корне неправильно »
|
и это тоже верно, лучше сделать чтоб лог записывался -1 (предыдущую) папку, иногда трудно попасть в папку из-за бооольшого кол-ва файлов.
|
Цитата:
Цитата Arsenik77
Цитата:
Цитата Iska
…нужно именно количество удалённых файлов? »
|
правильно мыслите, »
|
Примерно так:
читать дальше »
Код:
Option Explicit
' IOMode Enum
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
' Format Enum
Const TristateUseDefault = -2
Const TristateTrue = -1
Const TristateFalse = 0
Dim objFSO
Dim strFolder
Dim objFile
Dim objDictionary
Dim elem
Dim objTS
Dim lngCount
If WScript.Arguments.Count = 1 Then
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
strFolder = WScript.Arguments.Item(0)
If objFSO.FolderExists(strFolder) Then
Set objTS = objFSO.OpenTextFile( _
objFSO.BuildPath( _
objFSO.GetParentFolderName(WScript.ScriptFullName), _
objFSO.GetBaseName(WScript.ScriptFullName) & ".log" _
), ForAppending, True, TristateTrue)
objTS.WriteLine
objTS.WriteLine FormatDateTime(Now())
objTS.WriteLine
Set objDictionary = WScript.CreateObject("Scripting.Dictionary")
lngCount = 0
For Each objFile In objFSO.GetFolder(strFolder).Files
If objDictionary.Exists(objFile.Size) Then
objTS.WriteLine objFile.Path
objFSO.DeleteFile objFile.Path, True
lngCount = lngCount + 1
Else
objDictionary.Add objFile.Size, objFile.Path
End If
Next
objDictionary.RemoveAll
Set objDictionary = Nothing
objTS.WriteLine
objTS.WriteLine "Total delete: " & lngCount & " file(s)"
objTS.Close
Set objTS = Nothing
Else
WScript.Echo "Folder [" & strFolder & "] not found."
End If
Set objFSO = Nothing
Else
WScript.Echo "Usage: " & WScript.ScriptName & " <folder>"
End If
WScript.Quit 0
Цитата:
Цитата Arsenik77
лучше сделать чтоб лог записывался -1 (предыдущую) папку, »
|
Я не понял Вашу мысль. Поясните, пожалуйста, на примере.
|
нет список файлов не надо вообще, иногда он может быть ооочень большим.
Последний раз Ваш скрипт обработал 330 тыщ.файлов, удалив порядка 160 тыщи файлов.
Хотя если можно то ее можно оставить, включая или отключая её через ключ (параметр).
Можно добавить в логе писал: Total delete: YY file(s) из XXX файлов.
Цитата:
Цитата Iska
Я не понял Вашу мысль. Поясните, пожалуйста, на примере. »
|
вы уже реализовали её.
|
Цитата:
Цитата Arsenik77
Хотя если можно то ее можно оставить, включая или отключая её через ключ (параметр).
Можно добавить в логе писал: Total delete: YY file(s) из XXX файлов. »
|
Сделаем, но позже.
|
Arsenik77, сделал:
читать дальше »
Код:
<?xml version="1.0" encoding="windows-1251" standalone="yes" ?>
<package>
<job>
<?job error="True" Debug="True" ?>
<runtime>
<description>Description: Delete 'duplicate' files in folder by equal size</description>
<unnamed
name = "Folder"
helpstring = "Path to folder to scan"
many = "False"
required = "True"
/>
<named
name = "IncludeNames2Log"
helpstring = "Include paths of deleted files to log"
type = "Simple"
required = "False"
/>
<example>
Example: Script.wsf "c:\Temp" [/IncludeNames2Log]</example>
</runtime>
<reference object="Scripting.FileSystemObject" />
<object id="objFSO" progid="Scripting.FileSystemObject" />
<object id="objDictionary" progid="Scripting.Dictionary" />
<script language="VBScript">
<![CDATA[
Option Explicit
With WScript.Arguments
Select Case .Count
Case 1
If .Unnamed.Count = 1 Then
WScript.Quit Working(.Unnamed.Item(0), False)
End If
Case 2
If .Unnamed.Count = 1 And .Named.Count = 1 Then
If .Named.Exists("IncludeNames2Log") Then
WScript.Quit Working(.Unnamed.Item(0), True)
End If
End If
Case Else
' Nothing to do
End Select
End With
WScript.Echo "Error in arguments"
WScript.Echo
WScript.Arguments.ShowUsage()
WScript.Quit 1
'=========================================================================
'=========================================================================
Function Working(strFolder, boolIncludeNames2Log)
Dim collFiles
Dim objFile
Dim elem
Dim objTS
Dim lngTotalCount
Dim lngDeleteCount
If objFSO.FolderExists(strFolder) Then
Set objTS = objFSO.OpenTextFile( _
objFSO.BuildPath( _
objFSO.GetParentFolderName(WScript.ScriptFullName), _
objFSO.GetBaseName(WScript.ScriptFullName) & ".log" _
), ForAppending, True, TristateTrue)
objTS.WriteLine
objTS.WriteLine FormatDateTime(Now())
objTS.WriteLine
Set collFiles = objFSO.GetFolder(strFolder).Files
lngDeleteCount = 0
lngTotalCount = collFiles.Count
For Each objFile In collFiles
If objDictionary.Exists(objFile.Size) Then
If boolIncludeNames2Log Then
objTS.WriteLine objFile.Path
End If
objFSO.DeleteFile objFile.Path, True
lngDeleteCount = lngDeleteCount + 1
Else
objDictionary.Add objFile.Size, objFile.Path
End If
Next
Set collFiles = Nothing
objDictionary.RemoveAll
objTS.WriteLine
objTS.WriteLine "Deleted " & lngDeleteCount & " of " & lngTotalCount & " file(s)"
objTS.Close
Set objTS = Nothing
Working = 0
Else
WScript.Echo "Folder [" & strFolder & "] not found."
WScript.Echo
Working = 2
End If
End Function
'=========================================================================
]]>
</script>
</job>
</package>
Приведённый код сохранить в файл с расширением «.wsf» в кодировке ANSI (Windows-1251).
|
Время: 03:55.
© OSzone.net 2001-