Получив информацию о дублировании файлов, пользователь или администратор сможет проверить файлы и удалить ненужные копии, сэкономив место на дисках.
Принцип работы скрипта прост: сначала он сканирует заданную папку и составляет список файлов, затем выбирает одинаковые по размеру файлы и сравнивает их содержимое. В результате скрипт выявляет файлы с одинаковым содержимым, даже если они отличаются названием. Скрипт написан на JScript.
Сканирование и подготовка списка файлов выполняются рекурсивно через соответствующие методы File System Object.
Код: Выделить всё
var fso = WScript.CreateObject("Scripting.FileSystemObject");
var files = new Array;
scan(path);
function scan(path) {
var folder = fso.GetFolder(path);
for(var e = new Enumerator(folder.Files); !e.atEnd(); e.moveNext())
if (e.item().Size >= min_file_size)
files.push(e.item());
for(var e = new Enumerator(folder.SubFolders); !e.atEnd(); e.moveNext())
scan(e.item().Path);
}
Теперь необходимо выбрать из списка файлы, которые имеют одинаковое содержимое. Для этого список файлов сортируется по размеру файлов:
Код: Выделить всё
function sort_by_size(a,b){
if (a.size < b.size)
return (-1);
if (a.size > b.size)
return 1;
return 0;
}
files.sort(sort_by_size);
Код: Выделить всё
while (files.length > 1) {
var count = 0;
var fc = 0;
for (var i = 1; i < files.length && files[0].Size == files[i].Size;) {
fc = shell.Run("fc /b \"" +
files[0].ParentFolder + "\\" + files[0].Name + "\" \"" +
files[i].ParentFolder + "\\" + files[i].Name + "\"",0,true);
if (fc == 0) { // файлы одинаковые
WScript.StdOut.WriteLine(files[i].ParentFolder + "\\" + files[i].Name);
files.splice(i,1);
++count;
}
else
++i;
}
if (count) { // найдены копии файла files[0]
// выводим информацию о файлах или выполняем какие-то действия...
}
files.shift();
}
Недостатком является небольшая скорость работы из-за многократных сравнений.
Также скрипт не проверяет файлы в архивах (ZIP и т.п.), что было бы полезно для выявления файлов, копии которых есть и в папках, и в архивах.
Далее приведён полный текст скрипта с некоторыми изменениями и дополнениями:
- путь для проверки берётся из первого параметра командной строки.
- добавлено ограничение на минимальный размер файла (чтобы не проверять мелкие файлы).
- сортировка списка сделана в обратном порядке (по убыванию размера файлов), чтобы вывод программы начинался с более интересных "тяжёлых" файлов; сортировку легко изменить, заменив вызов files.sort(sort_by_size_desc) на files.sort(sort_by_size_asc).
- добавлен подсчёт, сколько места в байтах занимают копии.
Код: Выделить всё
var path = WScript.Arguments(0);
var fso = WScript.CreateObject("Scripting.FileSystemObject");
var shell = WScript.CreateObject("WScript.Shell");
var min_file_size = 1024; // минимальный размер файла для проверки
var files = new Array;
WScript.StdOut.WriteLine("Поиск одинаковых файлов в " + path);
scan(path);
WScript.StdOut.WriteLine("Выбрано файлов для сравнения " + files.length);
process();
WScript.Quit(0);
function scan(path) {
var folder = fso.GetFolder(path);
for(var e = new Enumerator(folder.Files); !e.atEnd(); e.moveNext())
if (e.item().Size >= min_file_size)
files.push(e.item());
for(var e = new Enumerator(folder.SubFolders); !e.atEnd(); e.moveNext())
scan(e.item().Path);
}
// сравнивает по возрастанию размера файла
function sort_by_size_asc(a,b) {
if (a.size < b.size)
return (-1);
if (a.size > b.size)
return 1;
return 0;
}
// сравнивает по убыванию размера файла
function sort_by_size_desc(a,b) {
if (a.size > b.size)
return (-1);
if (a.size < b.size)
return 1;
return 0;
}
// обработка списка файлов
function process(){
var total_count = 0, total_bytes = 0;
files.sort(sort_by_size_desc);
while (files.length > 1) {
var count = 0;
var fc = 0;
for (var i = 1; i < files.length && files[0].Size == files[i].Size;) {
fc = shell.Run("fc /b \"" +
files[0].ParentFolder + "\\" + files[0].Name + "\" \"" +
files[i].ParentFolder + "\\" + files[i].Name + "\"",0,true);
if (fc == 0) { // файлы одинаковые
WScript.StdOut.WriteLine(files[i].ParentFolder + "\\" + files[i].Name);
files.splice(i,1);
++count;
}
else
++i;
}
if (count) { // найдены копии файла files[0]
WScript.StdOut.WriteLine(files[0].ParentFolder + "\\" + files[0].Name);
var extra_bytes = files[0].Size * count;
WScript.StdOut.WriteLine("> " + ++count + " одинаковых файлов (" +
files[0].Size + " байт в каждом, " +
extra_bytes + " байт в копиях)");
++total_count;
total_bytes += extra_bytes;
}
files.shift();
}
WScript.StdOut.WriteLine("Всего " + total_bytes + " байт в " +
total_count + " копиях файлов");
}
Код: Выделить всё
cscript.exe //nologo files.js \\fileserver\users > users_duplicates.txt