Ru-Board.club
← Вернуться в раздел «Тестирование»

» Far Manager - скрипты и плагины

Автор: Alexyz21
Дата сообщения: 08.05.2016 11:54
12.3 [more]
Код: local F = far.Flags
local ffi = require'ffi'
local C = ffi.C

local PanelMode,Desc1,Indi1 = 999,"Custom: by name","!?"
local guid = "FE9B8874-9651-434C-8182-72329F2371A5"
local uGuid = win.Uuid(guid)
local BS,ts = string.byte("\\"),{nil,true,9999,true,true,false}
local freport = win.GetEnv("Temp").."\\Report.txt"
local Flags = C.SORT_STRINGSORT

ffi.cdef[[
int strcmp(const char*, const char*);
int _stricmp(const char*, const char*);
int _strnicmp(const char*, const char*, size_t);
int strncmp(const char*, const char*, size_t);
char* strrchr(const char*, int);
size_t strlen(const char*);
int memcmp(const void*, const void*, size_t);
wchar_t* wmemcpy(wchar_t*, const wchar_t*, size_t);
]]

local function GetStartAndLen(name)
local ptr = C.wcsrchr(name,BS)
name = ptr==nil and name or ptr+1
local len = tonumber(C.wcslen(name))
if ts[2] and ts[3]<0 and -ts[3]<len then
local res=ffi.new("wchar_t[?]",len+1)
ffi.copy(res,name+len+ts[3],-ts[3]*2)
ffi.copy(res-ts[3],name,(len+ts[3])*2)
return res,len
else
return name,len
end
end

local Compare = function(p1,p2)
local st1,ln1 = GetStartAndLen(p1.FileName)
local st2,ln2 = GetStartAndLen(p2.FileName)
return -2 + C.CompareStringW(C.LOCALE_USER_DEFAULT,Flags,st1,ln1,st2,ln2)
end

local function StartAndLen(name)
local ptr = C.strrchr(name,BS)
name = ptr==nil and name or ptr+1
local len = tonumber(C.strlen(name))
if ts[2] and ts[3]<0 and -ts[3]<len then
return name+len+ts[3],-ts[3],name,len
elseif ts[2] and ts[3]>0 and ts[3]<len then
return name,ts[3],name,len
else
return name,len,name,len
end
end

local Items = {
--[[01]] {F.DI_DOUBLEBOX, 3,1, 65,6, 0, 0,0, 0, "Select duplicates of FileName. Help: F1"},
--[[02]] {F.DI_CHECKBOX, 5,2, 26,2, 0, 0,0, 0, "Num&ber of symbols"},
--[[03]] {F.DI_EDIT, 27,2, 32,2, 0, 0,0, 0, ""},
--[[04]] {F.DI_CHECKBOX, 5,3, 20,3, 0, 0,0, 0, "Ignore &case"},
--[[05]] {F.DI_CHECKBOX, 37,3, 56,3, 0, 0,0, 0, "Ignore &full duplicates"},
--[[06]] {F.DI_CHECKBOX, 5,5, 15,5, 0, 0,0, 0, "Re&port"},
--[[07]] {F.DI_TEXT, -1,4, 0,0, 0, 0,0, F.DIF_SEPARATOR,""},
--[[08]] {F.DI_BUTTON, 0,5, 0,0, 0, 0,0, F.DIF_DEFAULTBUTTON+F.DIF_CENTERGROUP,"&Ok"},
--[[09]] {F.DI_BUTTON, 0,5, 0,0, 0, 0,0, F.DIF_CENTERGROUP,"Ca&ncel"}
}

local tts={}

local function DlgProc(hDlg,Msg,Param1,Param2)
if Msg==F.DN_INITDIALOG then
for i=2,#Items-3 do tts[i]=ts[i] end
hDlg:send(F.DM_SETTEXT,3,tts[3])
hDlg:send(F.DM_SETCHECK,2,tts[2] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,4,tts[4] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,5,tts[5] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,6,tts[6] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
elseif Msg==F.DN_BTNCLICK and (Param1==2 or Param1>=4 and Param1<=6) then
tts[Param1] = Param2~=0
elseif Msg==F.DN_EDITCHANGE and Param1==3 then -- Number symbols
tts[3] = tonumber(hDlg:send(F.DM_GETTEXT,3)) or tts[3]
else
return
end
return true
end

Macro {
description="* Select Duplicates FileName in Branch panel"; name="SDFN"; area="Shell";
action=function()
if far.Dialog(uGuid,-1,-1,69,8,nil,Items,nil,DlgProc)==#Items-1 then
local t0=far.FarClock()
for i=2,#Items-3 do ts[i]=tts[i] end
local pBL=ffi.cast("BOOL*",1)
local pc=ffi.cast("struct PluginStartupInfo*",far.CPluginStartupInfo()).PanelControl
local pin=panel.GetPanelInfo(nil,1)
if bit.band(pin.Flags,F.PFLAGS_SELECTEDFIRST)>0 then Keys("ShiftF12") end
pc(PANEL_ACTIVE,"FCTL_SETNUMERICSORT",0,nil)
pc(PANEL_ACTIVE,"FCTL_SETCASESENSITIVESORT",ts[4] and 0 or 1,nil)
if ((ts[2] and ts[3]>=0) or not ts[2]) then
pc(PANEL_ACTIVE,"FCTL_SETSORTMODE",F.SM_NAME,nil)
else
Flags = ts[4] and bit.bor(Flags,C.NORM_IGNORECASE) or bit.band(Flags,bit.bnot(C.NORM_IGNORECASE))
Panel.LoadCustomSortMode(PanelMode,{Description=Desc1;Indicator=Indi1;Compare=Compare})
Panel.SetCustomSortMode(PanelMode,0)
end
pc(PANEL_ACTIVE,"FCTL_SETSORTORDER",0,nil)
local sid,sel,fn0,fn1,fn2,fn3,st0,ln0,st1,ln1,st2,ln2,st3,ln3 = 0,{},"","","","",0,0,0,0,0,0,0,0
local function Comp(fn0,fn1)
if ts[4] then return C._stricmp(fn1,fn0)
elseif not ts[4] then return C.strcmp(fn1,fn0)
end
end
pc(PANEL_ACTIVE,"FCTL_BEGINSELECTION",0,nil)
for i=1,pin.ItemsNumber do
fn0,fn2 = fn1,fn3
st1,ln1,st3,ln3=StartAndLen(panel.GetPanelItem(nil,1,i).FileName)
fn1,fn3 = ffi.string(st1,ln1),ffi.string(st3,ln3)
if ts[4] and C._stricmp(fn1,fn0)==0 and not(ts[5] and C._stricmp(fn3,fn2)==0)
or not ts[4] and C.strcmp(fn1,fn0)==0 and not(ts[5] and C.strcmp(fn3,fn2)==0)
then
if #sel>0 and Comp(sel[#sel][1],fn0)~=0 or #sel==0 then
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-2,pBL)
table.insert(sel,{fn0,1})
sid=1
end
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-1,pBL)
sid = sid+1
sel[#sel][2]=sid
end
end
pc(PANEL_ACTIVE,"FCTL_ENDSELECTION",0,nil)
pc(PANEL_ACTIVE,"FCTL_REDRAWPANEL",0,nil)
Keys("ShiftF12")
if ts[6] then
table.sort(sel,function(a,b) return a[2]<b[2] end)
local h = io.open(freport,"wb")
io.close(h)
h = io.open(freport,"ab")
h:write("Items: "..#sel.."\nExecution time: "..(far.FarClock()-t0).." mcs\nNumber of symbols: "..(ts[2] and ts[3] or "all").."\nIgnore case: "..tostring(ts[4]).."\nIgnore full duplicates: "..tostring(ts[5]).."\n\n")
for i=#sel,1,-1 do h:write(sel[i][2].."\t"..sel[i][1].."\n") sel[i]=nil end
io.close(h)
far.Message("mcs: "..far.FarClock()-t0,"SDFN")
end
end
end;
}

Macro {
description = "SDFN - Help"; area = "Dialog"; key = "F1";
condition=function() return Area.Dialog and Dlg.Id==guid end;
action=function()
if Dlg.CurPos<=3 then far.Message("The number of first or last symbols to compare","Help: Number of symbols")
elseif Dlg.CurPos==4 then far.Message("Case of letters in FileName will be ignored","Help: Ignore case")
elseif Dlg.CurPos==5 then far.Message("Full duplicates of FileName will be ignored","Help: Ignore full duplicates")
elseif Dlg.CurPos==6 then far.Message("mcs - total time of execution in mcs\nReport will be saved to:\n"..freport,"Help: Report",nil,"l")
end
end;
}
Автор: Angel_Ka
Дата сообщения: 08.05.2016 12:14
Поторопился, запустил без бранча и получил ошибку:
Код: LuaMacro

...ar\Profile\Macros\scripts\she_lua\12.3_(Alexyz21)she.lua:48: attempt to perform arithmetic on local 'name' (a string value)
Stack Traceback
===============
(1) Lua function '(anonymous)' at file 'W:\Far\Profile\Macros\scripts\she_lua\12.3_(Alexyz21)she.lua:119' (best guess)
Local variables:
t0 = number: 1.66119e+08
pin = table: 0x32384268 {ViewMode:2, SortMode:2, PanelType:0, PanelRect:table: 0x32384290, TopPanelItem:1 (more...)}
sid = number: 0
sel = table: 0x32331470 {}
fn0 = string: ".."
fn1 = string: ".."
fn2 = string: ".."
fn3 = string: ".."
st0 = number: 0
ln0 = number: 0
st1 = string: ".."
ln1 = number: 2
st2 = number: 0
ln2 = number: 0
st3 = string: ".."
ln3 = number: 2
Comp = Lua function 'Comp' (defined at line 111 of chunk ...ar\Profile\Macros\scripts\she_lua\12.3_(Alexyz21)she.lua)
(for index) = number: 2
(for limit) = number: 80
(for step) = number: 1
i = number: 2
Автор: VictorVG4
Дата сообщения: 08.05.2016 13:05
Angel_Ka

А если снова попробовать объединить два скрипта - скрипт отвечающий за построение дерева на временной панели и этот? По идее может принести пользу. У меня он только страхует ситуацию когда плагин True-BRANCH по каким-то причина не запущен, но вызывается, а потому практически и не используется.
Автор: Angel_Ka
Дата сообщения: 08.05.2016 13:06
Перепроверил. На микротесте в бранче, в режиме:

Код: [x] Number of symbols -7
[x] Ignore case [x] Ignore full duplicates
Автор: Alexyz21
Дата сообщения: 08.05.2016 14:13
12.4 [more]
Код: local F = far.Flags
local ffi = require'ffi'
local C = ffi.C

local PanelMode,Desc1,Indi1 = 999,"Custom: by name","!?"
local guid = "FE9B8874-9651-434C-8182-72329F2371A5"
local uGuid = win.Uuid(guid)
local BS,ts = string.byte("\\"),{nil,true,9999,true,true,false}
local freport = win.GetEnv("Temp").."\\Report.txt"
local Flags = C.SORT_STRINGSORT

ffi.cdef[[
int strcmp(const char*, const char*);
int _stricmp(const char*, const char*);
int _strnicmp(const char*, const char*, size_t);
int strncmp(const char*, const char*, size_t);
char* strrchr(const char*, int);
size_t strlen(const char*);
int memcmp(const void*, const void*, size_t);
wchar_t* wmemcpy(wchar_t*, const wchar_t*, size_t);
]]

local function GetStartAndLen(name)
local ptr = C.wcsrchr(name,BS)
name = ptr==nil and ffi.cast("const wchar_t*",name) or ptr+1
local len = tonumber(C.wcslen(name))
if ts[2] and ts[3]<0 and -ts[3]<len then
local res=ffi.new("wchar_t[?]",len+1)
ffi.copy(res,name+len+ts[3],-ts[3]*2)
ffi.copy(res-ts[3],name,(len+ts[3])*2)
return res,len
else
return name,len
end
end

local Compare = function(p1,p2)
local st1,ln1 = GetStartAndLen(p1.FileName)
local st2,ln2 = GetStartAndLen(p2.FileName)
return -2 + C.CompareStringW(C.LOCALE_USER_DEFAULT,Flags,st1,ln1,st2,ln2)
end

local function StartAndLen(name)
local ptr = C.strrchr(name,BS)
name = ptr==nil and ffi.cast("const char*",name) or ptr+1
local len = tonumber(C.strlen(name))
if ts[2] and ts[3]<0 and -ts[3]<len then
return name+len+ts[3],-ts[3],name,len
elseif ts[2] and ts[3]>0 and ts[3]<len then
return name,ts[3],name,len
else
return name,len,name,len
end
end

local Items = {
--[[01]] {F.DI_DOUBLEBOX, 3,1, 65,6, 0, 0,0, 0, "Select duplicates of FileName. Help: F1"},
--[[02]] {F.DI_CHECKBOX, 5,2, 26,2, 0, 0,0, 0, "Num&ber of symbols"},
--[[03]] {F.DI_EDIT, 27,2, 32,2, 0, 0,0, 0, ""},
--[[04]] {F.DI_CHECKBOX, 5,3, 20,3, 0, 0,0, 0, "Ignore &case"},
--[[05]] {F.DI_CHECKBOX, 37,3, 56,3, 0, 0,0, 0, "Ignore &full duplicates"},
--[[06]] {F.DI_CHECKBOX, 5,5, 15,5, 0, 0,0, 0, "Re&port"},
--[[07]] {F.DI_TEXT, -1,4, 0,0, 0, 0,0, F.DIF_SEPARATOR,""},
--[[08]] {F.DI_BUTTON, 0,5, 0,0, 0, 0,0, F.DIF_DEFAULTBUTTON+F.DIF_CENTERGROUP,"&Ok"},
--[[09]] {F.DI_BUTTON, 0,5, 0,0, 0, 0,0, F.DIF_CENTERGROUP,"Ca&ncel"}
}

local tts={}

local function DlgProc(hDlg,Msg,Param1,Param2)
if Msg==F.DN_INITDIALOG then
for i=2,#Items-3 do tts[i]=ts[i] end
hDlg:send(F.DM_SETTEXT,3,tts[3])
hDlg:send(F.DM_SETCHECK,2,tts[2] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,4,tts[4] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,5,tts[5] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,6,tts[6] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
elseif Msg==F.DN_BTNCLICK and (Param1==2 or Param1>=4 and Param1<=6) then
tts[Param1] = Param2~=0
elseif Msg==F.DN_EDITCHANGE and Param1==3 then -- Number symbols
tts[3] = tonumber(hDlg:send(F.DM_GETTEXT,3)) or tts[3]
else
return
end
return true
end

Macro {
description="* Select Duplicates FileName in Branch panel"; name="SDFN"; area="Shell";
action=function()
if far.Dialog(uGuid,-1,-1,69,8,nil,Items,nil,DlgProc)==#Items-1 then
local t0=far.FarClock()
for i=2,#Items-3 do ts[i]=tts[i] end
local pBL=ffi.cast("BOOL*",1)
local pc=ffi.cast("struct PluginStartupInfo*",far.CPluginStartupInfo()).PanelControl
local pin=panel.GetPanelInfo(nil,1)
if bit.band(pin.Flags,F.PFLAGS_SELECTEDFIRST)>0 then Keys("ShiftF12") end
pc(PANEL_ACTIVE,"FCTL_SETNUMERICSORT",0,nil)
pc(PANEL_ACTIVE,"FCTL_SETCASESENSITIVESORT",ts[4] and 0 or 1,nil)
if ((ts[2] and ts[3]>=0) or not ts[2]) then
pc(PANEL_ACTIVE,"FCTL_SETSORTMODE",F.SM_NAME,nil)
else
Flags = ts[4] and bit.bor(Flags,C.NORM_IGNORECASE) or bit.band(Flags,bit.bnot(C.NORM_IGNORECASE))
Panel.LoadCustomSortMode(PanelMode,{Description=Desc1;Indicator=Indi1;Compare=Compare})
Panel.SetCustomSortMode(PanelMode,0)
end
pc(PANEL_ACTIVE,"FCTL_SETSORTORDER",0,nil)
local sid,sel,fn0,fn1,fn2,fn3,st0,ln0,st1,ln1,st2,ln2,st3,ln3 = 0,{},"","","","",0,0,0,0,0,0,0,0
local function Comp(fn0,fn1)
if ts[4] then return C._stricmp(fn1,fn0)
elseif not ts[4] then return C.strcmp(fn1,fn0)
end
end
pc(PANEL_ACTIVE,"FCTL_BEGINSELECTION",0,nil)
for i=1,pin.ItemsNumber do
fn0,fn2 = fn1,fn3
st1,ln1,st3,ln3=StartAndLen(panel.GetPanelItem(nil,1,i).FileName)
fn1,fn3 = ffi.string(st1,ln1),ffi.string(st3,ln3)
if ts[4] and C._stricmp(fn1,fn0)==0 and not(ts[5] and C._stricmp(fn3,fn2)==0)
or not ts[4] and C.strcmp(fn1,fn0)==0 and not(ts[5] and C.strcmp(fn3,fn2)==0)
then
if #sel>0 and Comp(sel[#sel][1],fn0)~=0 or #sel==0 then
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-2,pBL)
table.insert(sel,{fn0,1})
sid=1
end
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-1,pBL)
sid = sid+1
sel[#sel][2]=sid
end
end
pc(PANEL_ACTIVE,"FCTL_ENDSELECTION",0,nil)
pc(PANEL_ACTIVE,"FCTL_REDRAWPANEL",0,nil)
Keys("ShiftF12")
if ts[6] then
table.sort(sel,function(a,b) return a[2]<b[2] end)
local h = io.open(freport,"wb")
io.close(h)
h = io.open(freport,"ab")
h:write("Items: "..#sel.."\nExecution time: "..(far.FarClock()-t0).." mcs\nNumber of symbols: "..(ts[2] and ts[3] or "all").."\nIgnore case: "..tostring(ts[4]).."\nIgnore full duplicates: "..tostring(ts[5]).."\n\n")
for i=#sel,1,-1 do h:write(sel[i][2].."\t"..sel[i][1].."\n") sel[i]=nil end
io.close(h)
far.Message("mcs: "..far.FarClock()-t0,"SDFN")
end
end
end;
}

Macro {
description = "SDFN - Help"; area = "Dialog"; key = "F1";
condition=function() return Area.Dialog and Dlg.Id==guid end;
action=function()
if Dlg.CurPos<=3 then far.Message("The number of first or last symbols to compare","Help: Number of symbols")
elseif Dlg.CurPos==4 then far.Message("Case of letters in FileName will be ignored","Help: Ignore case")
elseif Dlg.CurPos==5 then far.Message("Full duplicates of FileName will be ignored","Help: Ignore full duplicates")
elseif Dlg.CurPos==6 then far.Message("mcs - total time of execution in mcs\nReport will be saved to:\n"..freport,"Help: Report",nil,"l")
end
end;
}
Автор: Angel_Ka
Дата сообщения: 08.05.2016 14:26
Alexyz21

Цитата:
Перепроверил. На микротесте в бранче, в режиме:

Код:
[x] Number of symbols -7
[x] Ignore case [x] Ignore full duplicates

Помечает в т.ч. полные дубли.

Похоже на то, что я этот момент в предыдущей (12.2) версии проворонил. Сейчас перепроверил и понял это. Приношу свои извинения! Впредь постараюсь быть более сосредоточенным и щепетильным в тестировании.

Добавлено:

Цитата:
12.4

Сейчас сосредоточусь на ней. Спасибо большое за труды!
Автор: Alexyz21
Дата сообщения: 08.05.2016 14:33

Цитата:
Бранчевание на тех объёмах, которые у нас практикуются, очень непропорционально медленная операция по сравнению с данным макросом.

Это вообще как? Макрос же не бранчует панель, он лишь сортирует то, что на ней есть. Если указано положительное Number of symbols, то панель сортируется "нативным" быстрым CtrlF3, если отрицательное, то такого нативного режима в FAR нет, поэтому задействуем CustomSort с перестановкой частей в строке. Получается медленно, но гарантированно группируются полные дубли. Хотелки отягощают алгоритм, бывший изначально быстрым.

Добавлено:

Цитата:
Похоже на то, что я этот момент в предыдущей (12.2) версии проворонил.

Что это значит? текущая помечает полные дубли при их игноре, или нет?
Автор: Angel_Ka
Дата сообщения: 08.05.2016 14:42
Да, 12.4 в вышеозначенном режиме (с выставленным [x] игнором) тоже помечает в т.ч. и полные дубли.

Добавлено:

Цитата:
Это вообще как?

Это я писал в ответ на предложение от VictorVG4 объединить макросы, и не имеет непосредственного отношения к данному макросу.
Цитата:
Хотелки отягощают алгоритм, бывший изначально быстрым.
Это мне вполне понятно и я более чем доволен тем, что получается. Макрос уже в данном, не доведённом ещё до конца виде, превосходит мои ожидания.

Автор: Alexyz21
Дата сообщения: 08.05.2016 14:59

Цитата:
тоже помечает в т.ч. и полные дубли.

настройки и Имена в студию, а также ссылку на тот вариант, который при этих настройках полные дубли не помечал.
Автор: Angel_Ka
Дата сообщения: 08.05.2016 15:14
Поясните, пожалуйста, какие именно настройки нужны.
Автор: VictorVG4
Дата сообщения: 08.05.2016 15:17
Angel_Ka

Это естественно - пока ось построит список, пока он скопируется на временную панель... У меня частенько задачи повеселее - есть дерево подмонтированное по NFS, там сотни гигабайт и десятки тысяч файлов с симлинками ведущими на десятки хостов и надо что-то быстро отыскать в дереве. И особенно весело коли симлинки на файл ведут на десятки каталогов. Например именно так построено дерево портов [more=FreeBSD UNIX]CHECKSUM.SHA256-FreeBSD-10.3-RELEASE-amd64
CHECKSUM.SHA256-FreeBSD-10.3-RELEASE-arm-armv6-BEAGLEBONE
CHECKSUM.SHA256-FreeBSD-10.3-RELEASE-arm-armv6-CUBOX-HUMMINGBOARD
CHECKSUM.SHA256-FreeBSD-10.3-RELEASE-arm-armv6-GUMSTIX
CHECKSUM.SHA256-FreeBSD-10.3-RELEASE-arm-armv6-PANDABOARD
CHECKSUM.SHA256-FreeBSD-10.3-RELEASE-arm-armv6-RPI-B
CHECKSUM.SHA256-FreeBSD-10.3-RELEASE-arm-armv6-WANDBOARD
CHECKSUM.SHA256-FreeBSD-10.3-RELEASE-i386
CHECKSUM.SHA256-FreeBSD-10.3-RELEASE-ia64
CHECKSUM.SHA256-FreeBSD-10.3-RELEASE-powerpc
CHECKSUM.SHA256-FreeBSD-10.3-RELEASE-powerpc-powerpc64
CHECKSUM.SHA256-FreeBSD-10.3-RELEASE-sparc64
CHECKSUM.SHA512-FreeBSD-10.3-RELEASE-amd64
CHECKSUM.SHA512-FreeBSD-10.3-RELEASE-arm-armv6-BEAGLEBONE
CHECKSUM.SHA512-FreeBSD-10.3-RELEASE-arm-armv6-CUBOX-HUMMINGBOARD
CHECKSUM.SHA512-FreeBSD-10.3-RELEASE-arm-armv6-GUMSTIX
CHECKSUM.SHA512-FreeBSD-10.3-RELEASE-arm-armv6-PANDABOARD
CHECKSUM.SHA512-FreeBSD-10.3-RELEASE-arm-armv6-RPI-B
CHECKSUM.SHA512-FreeBSD-10.3-RELEASE-arm-armv6-WANDBOARD
CHECKSUM.SHA512-FreeBSD-10.3-RELEASE-i386
CHECKSUM.SHA512-FreeBSD-10.3-RELEASE-ia64
CHECKSUM.SHA512-FreeBSD-10.3-RELEASE-powerpc
CHECKSUM.SHA512-FreeBSD-10.3-RELEASE-powerpc-powerpc64
CHECKSUM.SHA512-FreeBSD-10.3-RELEASE-sparc64
FreeBSD-10.3-RELEASE-amd64-bootonly.iso
FreeBSD-10.3-RELEASE-amd64-bootonly.iso.xz
FreeBSD-10.3-RELEASE-amd64-disc1.iso
FreeBSD-10.3-RELEASE-amd64-disc1.iso.xz
FreeBSD-10.3-RELEASE-amd64-dvd1.iso
FreeBSD-10.3-RELEASE-amd64-dvd1.iso.xz
FreeBSD-10.3-RELEASE-amd64-memstick.img
FreeBSD-10.3-RELEASE-amd64-memstick.img.xz
FreeBSD-10.3-RELEASE-amd64-mini-memstick.img
FreeBSD-10.3-RELEASE-amd64-mini-memstick.img.xz
FreeBSD-10.3-RELEASE-amd64-uefi-bootonly.iso
FreeBSD-10.3-RELEASE-amd64-uefi-bootonly.iso.xz
FreeBSD-10.3-RELEASE-amd64-uefi-disc1.iso
FreeBSD-10.3-RELEASE-amd64-uefi-disc1.iso.xz
FreeBSD-10.3-RELEASE-amd64-uefi-dvd1.iso
FreeBSD-10.3-RELEASE-amd64-uefi-dvd1.iso.xz
FreeBSD-10.3-RELEASE-amd64-uefi-memstick.img
FreeBSD-10.3-RELEASE-amd64-uefi-memstick.img.xz
FreeBSD-10.3-RELEASE-amd64-uefi-mini-memstick.img
FreeBSD-10.3-RELEASE-amd64-uefi-mini-memstick.img.xz
FreeBSD-10.3-RELEASE-arm-armv6-BEAGLEBONE.img.xz
FreeBSD-10.3-RELEASE-arm-armv6-CUBOX-HUMMINGBOARD.img.xz
FreeBSD-10.3-RELEASE-arm-armv6-GUMSTIX.img.xz
FreeBSD-10.3-RELEASE-arm-armv6-PANDABOARD.img.xz
FreeBSD-10.3-RELEASE-arm-armv6-RPI-B.img.xz
FreeBSD-10.3-RELEASE-arm-armv6-WANDBOARD.img.xz
FreeBSD-10.3-RELEASE-i386-bootonly.iso
FreeBSD-10.3-RELEASE-i386-bootonly.iso.xz
FreeBSD-10.3-RELEASE-i386-disc1.iso
FreeBSD-10.3-RELEASE-i386-disc1.iso.xz
FreeBSD-10.3-RELEASE-i386-dvd1.iso
FreeBSD-10.3-RELEASE-i386-dvd1.iso.xz
FreeBSD-10.3-RELEASE-i386-memstick.img
FreeBSD-10.3-RELEASE-i386-memstick.img.xz
FreeBSD-10.3-RELEASE-i386-mini-memstick.img
FreeBSD-10.3-RELEASE-i386-mini-memstick.img.xz
FreeBSD-10.3-RELEASE-ia64-bootonly.iso
FreeBSD-10.3-RELEASE-ia64-bootonly.iso.xz
FreeBSD-10.3-RELEASE-ia64-disc1.iso
FreeBSD-10.3-RELEASE-ia64-disc1.iso.xz
FreeBSD-10.3-RELEASE-ia64-memstick.img
FreeBSD-10.3-RELEASE-ia64-memstick.img.xz
FreeBSD-10.3-RELEASE-ia64-mini-memstick.img
FreeBSD-10.3-RELEASE-ia64-mini-memstick.img.xz
FreeBSD-10.3-RELEASE-powerpc-bootonly.iso
FreeBSD-10.3-RELEASE-powerpc-bootonly.iso.xz
FreeBSD-10.3-RELEASE-powerpc-disc1.iso
FreeBSD-10.3-RELEASE-powerpc-disc1.iso.xz
FreeBSD-10.3-RELEASE-powerpc-memstick.img
FreeBSD-10.3-RELEASE-powerpc-memstick.img.xz
FreeBSD-10.3-RELEASE-powerpc-mini-memstick.img
FreeBSD-10.3-RELEASE-powerpc-mini-memstick.img.xz
FreeBSD-10.3-RELEASE-powerpc-powerpc64-bootonly.iso
FreeBSD-10.3-RELEASE-powerpc-powerpc64-bootonly.iso.xz
FreeBSD-10.3-RELEASE-powerpc-powerpc64-disc1.iso
FreeBSD-10.3-RELEASE-powerpc-powerpc64-disc1.iso.xz
FreeBSD-10.3-RELEASE-powerpc-powerpc64-memstick.img
FreeBSD-10.3-RELEASE-powerpc-powerpc64-memstick.img.xz
FreeBSD-10.3-RELEASE-powerpc-powerpc64-mini-memstick.img
FreeBSD-10.3-RELEASE-powerpc-powerpc64-mini-memstick.img.xz
FreeBSD-10.3-RELEASE-sparc64-bootonly.iso
FreeBSD-10.3-RELEASE-sparc64-bootonly.iso.xz
FreeBSD-10.3-RELEASE-sparc64-disc1.iso
FreeBSD-10.3-RELEASE-sparc64-disc1.iso.xz[/more] (ports.tar.gz) - сами файлы лежат в /All , а с них на дерево кинуты симлинки. Файлов не сильно много - порядка 23 - 25 тысяч и размер в /All всего-то несколько десятков гигабайт, но коли копировать структуру дерева, то можно запросто получить вместо 41 Гб портов FreeBSD 9.1 порядка 140 - 150 Гб при числе файлов под 100 тыс. А первоначально их около 24 тысяч. И это не отдельные файлы а тарбаллы содержащие в себе фрагмент файловой системы со всеми правами доступа - tar сохраняет точную копию указанного фрагмента ФС с учётом всех файловых разрешений, хардлинков и симлинков. Это UNIX, а не винда и там утилиты резервного копирования ФС (dd, dup/restore, tar) доведены до совершенства.
Автор: Angel_Ka
Дата сообщения: 08.05.2016 15:18

Код: [x] Number of symbols -7
[x] Ignore case [x] Ignore full duplicates

Имена файлов, которые не должны быть помеченными в результате:

W:\farProf\tstSort\ПРОБА2\дублиПолные\72009 ГОСТ 12.0.005-84 Метрологическое обеспечение в области безопасности труда. Основные положения.2001.pdf
W:\farProf\tstSort\ПРОБА2\72009 ГОСТ 12.0.005-84 Метрологическое обеспечение в области безопасности труда. Основные положения.2001.pdf

W:\farProf\tstSort\ПРОБА2\дублиПолные\72001 СанПиН ]2.2.2_2.4.1340-03[ Гигиенические требования к персональным электронно-вычислительным машинам и организации работы 2003.pdf
W:\farProf\tstSort\ПРОБА2\72001 СанПиН ]2.2.2_2.4.1340-03[ Гигиенические требования к персональным электронно-вычислительным машинам и организации работы 2003.pdf

W:\farProf\tstSort\ПРОБА2\дублиПолные\72021 ГОСТ 26824-2010 ЗДАНИЯ И СООРУЖЕНИЯ Методы ]Ббк68.405к[измерения яркости.pdf
W:\farProf\tstSort\ПРОБА2\72021 ГОСТ 26824-2010 ЗДАНИЯ И СООРУЖЕНИЯ Методы ]Ббк68.405к[измерения яркости.pdf
Автор: Alexyz21
Дата сообщения: 08.05.2016 15:38
Angel_Ka
Портянки - удалить. Ломать глаза не собираюсь. Приведите настройки и выданные полные дубли, которых, по вашему мнению, там быть не должно.

Настройки выводятся в шапке Report.txt, например:
Items: 1706
Execution time: 1299179 mcs
Number of symbols: 5
Ignore case: true
Ignore full duplicates: true
Автор: Angel_Ka
Дата сообщения: 08.05.2016 15:50
Настройки поместил в пост выше.
Автор: Alexyz21
Дата сообщения: 08.05.2016 15:51

Цитата:
Имена файлов, которые не должны быть помеченными в результате

Это почему? - Где у них полное совпадение имён?
Автор: Angel_Ka
Дата сообщения: 08.05.2016 15:58

Цитата:
Где у них полное совпадение имён?

Добавил парные в тот пост.

Добавлено:
Чтобы дубли быстро различать в микротесте я их теперь, после моей осечки, поместил в папки с соответствующими им именами:

Код: W:\farProf\tstSort\ПРОБА2\дублиПолные
W:\farProf\tstSort\ПРОБА2\частичныеОтКонца
W:\farProf\tstSort\ПРОБА2\частичныеОтНачала
Автор: Alexyz21
Дата сообщения: 08.05.2016 16:06
На панели после отработки макроса они рядом находятся?
Автор: Angel_Ka
Дата сообщения: 08.05.2016 16:10
VictorVG4
Спасибо за информацию, полезную для расширения кругозора! Но вот на практике вряд ли бы у меня столько инфы в голове удержалось. И как Вы только управляетесь с таким хозяйством!
Автор: VictorVG4
Дата сообщения: 08.05.2016 16:11
Angel_Ka

Не сложно, да и привычка.
Автор: Angel_Ka
Дата сообщения: 08.05.2016 16:18

Цитата:
На панели после отработки макроса они рядом находятся?

Перезагрузил Фар, трижды запустил макрос, выделенной осталась только одна пара полных дублей:

Код: W:\farProf\tstSort\ПРОБА2\дублиПолные\72001 СанПиН ]2.2.2_2.4.1340-03[ Гигиенические требования к персональным электронно-вычислительным машинам и организации работы 2003.pdf
W:\farProf\tstSort\ПРОБА2\72001 СанПиН ]2.2.2_2.4.1340-03[ Гигиенические требования к персональным электронно-вычислительным машинам и организации работы 2003.pdf
Автор: VictorVG4
Дата сообщения: 08.05.2016 16:36
Angel_Ka

А это не хардлинки? Что-то у меня такая гипотеза в голове крутится. Можно глянуть по Ctrl9 на панели.
Автор: Alexyz21
Дата сообщения: 08.05.2016 16:54
Angel_Ka
12.4 [more]
Код: local F = far.Flags
local ffi = require'ffi'
local C = ffi.C

local PanelMode,Desc1,Indi1 = 999,"Custom: by name","!?"
local guid = "FE9B8874-9651-434C-8182-72329F2371A5"
local uGuid = win.Uuid(guid)
local BS,ts = string.byte("\\"),{nil,true,9999,true,true,false}
local freport = win.GetEnv("Temp").."\\Report.txt"
local Flags = C.SORT_STRINGSORT

ffi.cdef[[
int strcmp(const char*, const char*);
int _stricmp(const char*, const char*);
int _strnicmp(const char*, const char*, size_t);
int strncmp(const char*, const char*, size_t);
char* strrchr(const char*, int);
size_t strlen(const char*);
int memcmp(const void*, const void*, size_t);
wchar_t* wmemcpy(wchar_t*, const wchar_t*, size_t);
]]

local function GetStartAndLen(name)
local ptr = C.wcsrchr(name,BS)
name = ptr==nil and ffi.cast("const wchar_t*",name) or ptr+1
local len = tonumber(C.wcslen(name))
if ts[2] and ts[3]<0 and -ts[3]<len then
local res=ffi.new("wchar_t[?]",len+1)
ffi.copy(res,name+len+ts[3],-ts[3]*2)
ffi.copy(res-ts[3],name,(len+ts[3])*2)
return res,len
else
return name,len
end
end

local Compare = function(p1,p2)
local st1,ln1 = GetStartAndLen(p1.FileName)
local st2,ln2 = GetStartAndLen(p2.FileName)
--msgbox(win.Utf16ToUtf8(ffi.string(st1,ln1*2)),win.Utf16ToUtf8(ffi.string(st2,ln2*2)))
return -2 + C.CompareStringW(C.LOCALE_USER_DEFAULT,Flags,st1,ln1,st2,ln2)
end

local function StartAndLen(name)
local ptr = C.strrchr(name,BS)
name = ptr==nil and ffi.cast("const char*",name) or ptr+1
local len = tonumber(C.strlen(name))
if ts[2] and ts[3]<0 and -ts[3]<len then
return name+len+ts[3],-ts[3],name,len
elseif ts[2] and ts[3]>0 and ts[3]<len then
return name,ts[3],name,len
else
return name,len,name,len
end
end

local Items = {
--[[01]] {F.DI_DOUBLEBOX, 3,1, 65,6, 0, 0,0, 0, "Select duplicates of FileName. Help: F1"},
--[[02]] {F.DI_CHECKBOX, 5,2, 26,2, 0, 0,0, 0, "Num&ber of symbols"},
--[[03]] {F.DI_EDIT, 27,2, 32,2, 0, 0,0, 0, ""},
--[[04]] {F.DI_CHECKBOX, 5,3, 20,3, 0, 0,0, 0, "Ignore &case"},
--[[05]] {F.DI_CHECKBOX, 37,3, 56,3, 0, 0,0, 0, "Ignore &full duplicates"},
--[[06]] {F.DI_CHECKBOX, 5,5, 15,5, 0, 0,0, 0, "Re&port"},
--[[07]] {F.DI_TEXT, -1,4, 0,0, 0, 0,0, F.DIF_SEPARATOR,""},
--[[08]] {F.DI_BUTTON, 0,5, 0,0, 0, 0,0, F.DIF_DEFAULTBUTTON+F.DIF_CENTERGROUP,"&Ok"},
--[[09]] {F.DI_BUTTON, 0,5, 0,0, 0, 0,0, F.DIF_CENTERGROUP,"Ca&ncel"}
}

local tts={}

local function DlgProc(hDlg,Msg,Param1,Param2)
if Msg==F.DN_INITDIALOG then
for i=2,#Items-3 do tts[i]=ts[i] end
hDlg:send(F.DM_SETTEXT,3,tts[3])
hDlg:send(F.DM_SETCHECK,2,tts[2] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,4,tts[4] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,5,tts[5] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,6,tts[6] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
elseif Msg==F.DN_BTNCLICK and (Param1==2 or Param1>=4 and Param1<=6) then
tts[Param1] = Param2~=0
elseif Msg==F.DN_EDITCHANGE and Param1==3 then -- Number symbols
tts[3] = tonumber(hDlg:send(F.DM_GETTEXT,3)) or tts[3]
else
return
end
return true
end

Macro {
description="* Select Duplicates FileName in Branch panel"; name="SDFN"; area="Shell";
action=function()
if far.Dialog(uGuid,-1,-1,69,8,nil,Items,nil,DlgProc)==#Items-1 then
local t0=far.FarClock()
for i=2,#Items-3 do ts[i]=tts[i] end
local pBL1=ffi.cast("BOOL*",1)
local pBL0=ffi.cast("BOOL*",0)
local pc=ffi.cast("struct PluginStartupInfo*",far.CPluginStartupInfo()).PanelControl
local pin=panel.GetPanelInfo(nil,1)
if bit.band(pin.Flags,F.PFLAGS_SELECTEDFIRST)>0 then Keys("ShiftF12") end
pc(PANEL_ACTIVE,"FCTL_SETNUMERICSORT",0,nil)
pc(PANEL_ACTIVE,"FCTL_SETCASESENSITIVESORT",ts[4] and 0 or 1,nil)
if ((ts[2] and ts[3]>=0) or not ts[2]) then
pc(PANEL_ACTIVE,"FCTL_SETSORTMODE",F.SM_NAME,nil)
else
Flags = ts[4] and bit.bor(Flags,C.NORM_IGNORECASE) or bit.band(Flags,bit.bnot(C.NORM_IGNORECASE))
Panel.LoadCustomSortMode(PanelMode,{Description=Desc1;Indicator=Indi1;Compare=Compare})
Panel.SetCustomSortMode(PanelMode,0)
end
pc(PANEL_ACTIVE,"FCTL_SETSORTORDER",0,nil)
local sid,sel,fn0,fn1,fn2,fn3,st0,ln0,st1,ln1,st2,ln2,st3,ln3 = 0,{},"","","","",0,0,0,0,0,0,0,0
local function Comp(fn0,fn1)
return ts[4] and C._stricmp(fn1,fn0) or C.strcmp(fn1,fn0)
end
local function Proc(i,x)
if x then
if #sel>0 and Comp(sel[#sel][1],fn0)~=0 or #sel==0 then
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-2,pBL1)
table.insert(sel,{fn0,1})
sid=1
end
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-1,pBL1)
sid = sid+1
sel[#sel][2]=sid
else
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-2,pBL0)
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-1,pBL0)
end
end
pc(PANEL_ACTIVE,"FCTL_BEGINSELECTION",0,nil)
for i=1,pin.ItemsNumber do
fn0,fn2 = fn1,fn3
st1,ln1,st3,ln3=StartAndLen(panel.GetPanelItem(nil,1,i).FileName)
fn1,fn3 = ffi.string(st1,ln1),ffi.string(st3,ln3)
--msgbox(fn1,fn3)
--fn0,fn1 = fn1,string.gsub(panel.GetPanelItem(nil,1,i).FileName,"^.+\\","")
--if ln1==ln0 and C.memcmp(st1,st0,ln1)==0 then
--if fn1==fn0 then
if ts[4] and C._stricmp(fn1,fn0)==0 then Proc(i,not(ts[5] and C._stricmp(fn3,fn2)==0))
elseif not ts[4] and C.strcmp(fn1,fn0)==0 then Proc(i,not(ts[5] and C.strcmp(fn3,fn2)==0))
end
end
pc(PANEL_ACTIVE,"FCTL_ENDSELECTION",0,nil)
pc(PANEL_ACTIVE,"FCTL_REDRAWPANEL",0,nil)
Keys("ShiftF12")
if ts[6] then
table.sort(sel,function(a,b) return a[2]<b[2] end)
local h = io.open(freport,"wb")
io.close(h)
h = io.open(freport,"ab")
h:write("Items: "..#sel.."\nExecution time: "..(far.FarClock()-t0).." mcs\nNumber of symbols: "..(ts[2] and ts[3] or "all").."\nIgnore case: "..tostring(ts[4]).."\nIgnore full duplicates: "..tostring(ts[5]).."\n\n")
for i=#sel,1,-1 do h:write(sel[i][2].."\t"..sel[i][1].."\n") sel[i]=nil end
io.close(h)
far.Message("mcs: "..far.FarClock()-t0,"SDFN")
end
end
end;
}

Macro {
description = "SDFN - Help"; area = "Dialog"; key = "F1";
condition=function() return Area.Dialog and Dlg.Id==guid end;
action=function()
if Dlg.CurPos<=3 then far.Message("The number of first or last symbols to compare","Help: Number of symbols")
elseif Dlg.CurPos==4 then far.Message("Case of letters in FileName will be ignored","Help: Ignore case")
elseif Dlg.CurPos==5 then far.Message("Full duplicates of FileName will be ignored","Help: Ignore full duplicates")
elseif Dlg.CurPos==6 then far.Message("mcs - total time of execution in mcs\nReport will be saved to:\n"..freport,"Help: Report",nil,"l")
end
end;
}
Автор: Angel_Ka
Дата сообщения: 08.05.2016 16:55
А режим показа панели, в принципе, может влиять на сортировку? Ведь, если я правильно понимаю, только в режиме "широкий" (Ctrl+4) видны полные пути файлов. А у меня на одной "широкий", а на второй "средний" (Ctrl+2).
Автор: Alexyz21
Дата сообщения: 08.05.2016 16:58

Цитата:
трижды запустил макрос, выделенной осталась только одна пара полных дублей

Это к вопросу о "стабильности" алгоритма сортировки в функции MS CompareStringW (если речь идёт об отрицательных смещениях), при положительных используется сортировка FAR'a. Стабильные алгоритмы сортировок более медленные.

Добавлено:
Режим показа не влияет
Автор: Angel_Ka
Дата сообщения: 08.05.2016 17:00
12.4 уже была, это тогда 12.5?
Сейчас же внимательно посмотрю работу этой версии.

Микротест версия прошла, кажется, отлично. Потоптался на выявлении только полных дубликатов, похожих от начала и с исключением полных дубликатов, похожих от начала и не исключая полные дубликаты, похожих с конца и с исключением полных дубликатов, похожих с конца и не исключая полные дубликаты. В последнем случае количество помеченных наибольшее. И на сей раз не помеченных или лишних помеченных не обнаружено. Очень пока хорошо. Продолжу теперь на бранче с 546804 файлами.

Бранч тот же, на 546804 файла

В сопоставлении "12.2 по полной" и "12.5 без сортировки":

Код: [x] Number of symbols 37
[x] Ignore case [x] Ignore full duplicates

mcs: 22 302 543 mcs: 22 204 919 mcs: 19 241 480
mcs: 14 932 627 mcs: 15 113 107 mcs: 15 078 148

[x] Number of symbols 37
[x] Ignore case [ ] Ignore full duplicates

mcs: 23 789 175 mcs: 20 631 144 mcs: 23 698 635
mcs: 15 828 085 mcs: 15 792 908 mcs: 15 822 217

[x] Number of symbols -7
[x] Ignore case [x] Ignore full duplicates

mcs: 311 075 292 mcs: 310 280 472 mcs: 306 009 337
mcs: 158 377 409 mcs: 207 345 303 mcs: 207 401 901


[x] Number of symbols -7
[x] Ignore case [ ] Ignore full duplicates

mcs: 412 268 396 mcs: 412 545 659 mcs: 411 739 403
mcs: 207 554 264 mcs: 208 836 096 mcs: 209 302 548
Автор: Alexyz21
Дата сообщения: 08.05.2016 18:23
12.6 [more]
Код: local F = far.Flags
local ffi = require'ffi'
local C = ffi.C

local PanelMode,Desc1,Indi1 = 999,"Custom: by name","!?"
local guid = "FE9B8874-9651-434C-8182-72329F2371A5"
local uGuid = win.Uuid(guid)
local BS,ts = string.byte("\\"),{nil,true,9999,true,true,false}
local freport = win.GetEnv("Temp").."\\Report.txt"
local Flags = C.SORT_STRINGSORT

ffi.cdef[[
int strcmp(const char*, const char*);
int _stricmp(const char*, const char*);
int _strnicmp(const char*, const char*, size_t);
int strncmp(const char*, const char*, size_t);
char* strrchr(const char*, int);
size_t strlen(const char*);
int memcmp(const void*, const void*, size_t);
wchar_t* wmemcpy(wchar_t*, const wchar_t*, size_t);
]]

local function GetStartAndLen(name)
local ptr = C.wcsrchr(name,BS)
name = ptr==nil and ffi.cast("const wchar_t*",name) or ptr+1
local len = tonumber(C.wcslen(name))
if ts[2] and ts[3]<0 and -ts[3]<len then
local res=ffi.new("wchar_t[?]",len+1)
ffi.copy(res,name+len+ts[3],-ts[3]*2)
ffi.copy(res-ts[3],name,(len+ts[3])*2)
return res,len
else
return name,len
end
end

local Compare = function(p1,p2)
local st1,ln1 = GetStartAndLen(p1.FileName)
local st2,ln2 = GetStartAndLen(p2.FileName)
return -2 + C.CompareStringW(C.LOCALE_USER_DEFAULT,Flags,st1,ln1,st2,ln2)
end

local function StartAndLen(name)
local ptr = C.strrchr(name,BS)
name = ptr==nil and ffi.cast("const char*",name) or ptr+1
local len = tonumber(C.strlen(name))
if ts[2] and ts[3]<0 and -ts[3]<len then
return name+len+ts[3],-ts[3],name,len
elseif ts[2] and ts[3]>0 and ts[3]<len then
return name,ts[3],name,len
else
return name,len,name,len
end
end

local Items = {
--[[01]] {F.DI_DOUBLEBOX, 3,1, 65,6, 0, 0,0, 0, "Select duplicates of FileName. Help: F1"},
--[[02]] {F.DI_CHECKBOX, 5,2, 26,2, 0, 0,0, 0, "Num&ber of symbols"},
--[[03]] {F.DI_EDIT, 27,2, 32,2, 0, 0,0, 0, ""},
--[[04]] {F.DI_CHECKBOX, 5,3, 20,3, 0, 0,0, 0, "Ignore &case"},
--[[05]] {F.DI_CHECKBOX, 37,3, 56,3, 0, 0,0, 0, "Ignore &full duplicates"},
--[[06]] {F.DI_CHECKBOX, 5,5, 15,5, 0, 0,0, 0, "Re&port"},
--[[07]] {F.DI_TEXT, -1,4, 0,0, 0, 0,0, F.DIF_SEPARATOR,""},
--[[08]] {F.DI_BUTTON, 0,5, 0,0, 0, 0,0, F.DIF_DEFAULTBUTTON+F.DIF_CENTERGROUP,"&Ok"},
--[[09]] {F.DI_BUTTON, 0,5, 0,0, 0, 0,0, F.DIF_CENTERGROUP,"Ca&ncel"}
}

local tts={}

local function DlgProc(hDlg,Msg,Param1,Param2)
if Msg==F.DN_INITDIALOG then
for i=2,#Items-3 do tts[i]=ts[i] end
hDlg:send(F.DM_SETTEXT,3,tts[3])
hDlg:send(F.DM_SETCHECK,2,tts[2] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,4,tts[4] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,5,tts[5] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
hDlg:send(F.DM_SETCHECK,6,tts[6] and F.BSTATE_CHECKED or F.BSTATE_UNCHECKED)
elseif Msg==F.DN_BTNCLICK and (Param1==2 or Param1>=4 and Param1<=6) then
tts[Param1] = Param2~=0
elseif Msg==F.DN_EDITCHANGE and Param1==3 then -- Number symbols
tts[3] = tonumber(hDlg:send(F.DM_GETTEXT,3)) or tts[3]
else
return
end
return true
end

Macro {
description="* Select Duplicates FileName in Branch panel"; name="SDFN"; area="Shell";
action=function()
if far.Dialog(uGuid,-1,-1,69,8,nil,Items,nil,DlgProc)==#Items-1 then
local t0=far.FarClock()
for i=2,#Items-3 do ts[i]=tts[i] end
local pBL0,pBL1 = ffi.cast("BOOL*",0),ffi.cast("BOOL*",1)
local pc=ffi.cast("struct PluginStartupInfo*",far.CPluginStartupInfo()).PanelControl
local pin=panel.GetPanelInfo(nil,1)
if bit.band(pin.Flags,F.PFLAGS_SELECTEDFIRST)>0 then Keys("ShiftF12") end
pc(PANEL_ACTIVE,"FCTL_SETNUMERICSORT",0,nil)
pc(PANEL_ACTIVE,"FCTL_SETCASESENSITIVESORT",ts[4] and 0 or 1,nil)
if ((ts[2] and ts[3]>=0) or not ts[2]) then
pc(PANEL_ACTIVE,"FCTL_SETSORTMODE",F.SM_NAME,nil)
else
Flags = ts[4] and bit.bor(Flags,C.NORM_IGNORECASE) or bit.band(Flags,bit.bnot(C.NORM_IGNORECASE))
Panel.LoadCustomSortMode(PanelMode,{Description=Desc1;Indicator=Indi1;Compare=Compare})
Panel.SetCustomSortMode(PanelMode,0)
end
pc(PANEL_ACTIVE,"FCTL_SETSORTORDER",0,nil)
local full,sid,sel,fn0,fn1,fn2,fn3,st0,ln0,st1,ln1,st2,ln2,st3,ln3 = false,0,{},"","","","",0,0,0,0,0,0,0,0
local function Comp(fn0,fn1)
return ts[4] and C._stricmp(fn1,fn0) or C.strcmp(fn1,fn0)
end
local function Proc(i,x)
if ts[5] and x then
if not full then
if sid>1 then
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-2,pBL0)
sid=sid-1
sel[#sel][2]=sid
end
full=true
end
else
if full then
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-1,pBL1)
if #sel>0 and Comp(sel[#sel][1],fn1)~=0 or #sel==0 then
table.insert(sel,{fn1,1})
sid=1
else
sid=sid+1
sel[#sel][2]=sid
end
full=false
else
if #sel>0 and Comp(sel[#sel][1],fn0)~=0 or #sel==0 then
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-2,pBL1)
table.insert(sel,{fn0,1})
sid=1
end
pc(PANEL_ACTIVE,"FCTL_SETSELECTION",i-1,pBL1)
sid=sid+1
sel[#sel][2]=sid
end
end
end
pc(PANEL_ACTIVE,"FCTL_BEGINSELECTION",0,nil)
for i=1,pin.ItemsNumber do
fn0,fn2 = fn1,fn3
st1,ln1,st3,ln3=StartAndLen(panel.GetPanelItem(nil,1,i).FileName)
fn1,fn3 = ffi.string(st1,ln1),ffi.string(st3,ln3)
if ts[4] and C._stricmp(fn1,fn0)==0 then Proc(i,C._stricmp(fn3,fn2)==0)
elseif not ts[4] and C.strcmp(fn1,fn0)==0 then Proc(i,C.strcmp(fn3,fn2)==0)
end
end
pc(PANEL_ACTIVE,"FCTL_ENDSELECTION",0,nil)
pc(PANEL_ACTIVE,"FCTL_REDRAWPANEL",0,nil)
Keys("ShiftF12")
if ts[6] then
table.sort(sel,function(a,b) return a[2]<b[2] end)
local h = io.open(freport,"wb")
io.close(h)
h = io.open(freport,"ab")
h:write("Items: "..#sel.."\nExecution time: "..(far.FarClock()-t0).." mcs\nNumber of symbols: "..(ts[2] and ts[3] or "all").."\nIgnore case: "..tostring(ts[4]).."\nIgnore full duplicates: "..tostring(ts[5]).."\n\n")
for i=#sel,1,-1 do h:write(sel[i][2].."\t"..sel[i][1].."\n") sel[i]=nil end
io.close(h)
far.Message("mcs: "..far.FarClock()-t0,"SDFN")
end
end
end;
}

Macro {
description = "SDFN - Help"; area = "Dialog"; key = "F1";
condition=function() return Area.Dialog and Dlg.Id==guid end;
action=function()
if Dlg.CurPos<=3 then far.Message("The number of first or last symbols to compare","Help: Number of symbols")
elseif Dlg.CurPos==4 then far.Message("Case of letters in FileName will be ignored","Help: Ignore case")
elseif Dlg.CurPos==5 then far.Message("Full duplicates of FileName will be ignored","Help: Ignore full duplicates")
elseif Dlg.CurPos==6 then far.Message("mcs - total time of execution in mcs\nReport will be saved to:\n"..freport,"Help: Report",nil,"l")
end
end;
}
Автор: Angel_Ka
Дата сообщения: 08.05.2016 18:36

Цитата:
Ну теперь, надеюсь, учёл все его "выкрутасы".

Даже и после полного завершения работы над макросом не возбраняется ведь
вносить в него улучшения, если чего.

Цитата:
12.6.1

БОЛЬШОЕ СПАСИБО! Приступаю помаленьку.

Чуть было не сообщил, что макрос не выделил 2 полных дубликата, поскольку я заведомо знаю, что в сборке их 5 пар, а макрос выделил только 4. Но потом я решил сначала выяснить, какая именно это пара файлов, и оказалось следующее.
Поскольку тест маленький, то я после перезагрузки Фара решил не вызывать плагин, а собрать бранч консольной командой. И обнаружилось, что команда dir имя файла
"72024 МУ 3911-85 «Методические указания по проведению измерений и гигиенической оценки производственных вибраций 2001»"
преобразовывает в
"72024 МУ 3911-85 <Методические указания по проведению измерений и гигиенической оценки производственных вибраций 2001>"
и пара с этими именами не попадает в бранч. Тогда как плагин обрабатывает их правильно.

Микротест, сформированный в бранч плагином, макрос прошёл отлично! Не вызвал больше ни одного сомнения.

Посмотрим теперь его на бранче побольше.

Код: Бранч тот же, на 546804 файла

В сопоставлении "12.2", "12.5 без сортировки" и "12.6.1 без сортировки":

[x] Number of symbols 37
[x] Ignore case [x] Ignore full duplicates

mcs: 22 302 543 mcs: 22 204 919 mcs: 19 241 480
mcs: 14 932 627 mcs: 15 113 107 mcs: 15 078 148
mcs: 14 658 470 mcs: 14 964 966 mcs: 15 018 812

[x] Number of symbols 37
[x] Ignore case [ ] Ignore full duplicates

mcs: 23 789 175 mcs: 20 631 144 mcs: 23 698 635
mcs: 15 828 085 mcs: 15 792 908 mcs: 15 822 217
mcs: 15 800 623 mcs: 15 906 187 mcs: 15 922 663

[x] Number of symbols -7
[x] Ignore case [x] Ignore full duplicates

mcs: 311 075 292 mcs: 310 280 472 mcs: 306 009 337
mcs: 158 377 409 mcs: 207 345 303 mcs: 207 401 901
mcs: 131 013 726 mcs: 169 986 963 mcs: 208 659 930

[x] Number of symbols -7
[x] Ignore case [ ] Ignore full duplicates

mcs: 412 268 396 mcs: 412 545 659 mcs: 411 739 403
mcs: 207 554 264 mcs: 208 836 096 mcs: 209 302 548
mcs: 208 231 625 mcs: 211 652 721 mcs: 208 700 348
Автор: Angel_Ka
Дата сообщения: 08.05.2016 22:22
VictorVG4

Цитата:
А это не хардлинки?

Нет, это малюсенькая тестовая база, которую сам же я и формировал, исходя из опыта "работы над ошибками" на реальных базах.
Автор: Angel_Ka
Дата сообщения: 09.05.2016 06:18
Alexyz21

Порадуйтесь, пожалуйста, тому, какой очередной замечательный макрос Вы сделали! Вот посмотрите, например, что пишут в рекламе одной из программ "с быстрым алгоритмом поиска": "Начнётся поиск дубликатов. Это может занять довольно много времени. У меня на работе на ... было 1.35 миллиона файлов. Поиск занял чуть больше 20 часов". А, как Вы помните, в базе с 1.8 миллиона файлов поиск дубликатов созданным Вами макросом занял меньше 15 секунд.

Код: Версия 12.6 от 18:41 08-05-2016

база на 2,9 млн (2 890 330) файлов

С отключённой сортировкой, чисто функции:

[x] Number of symbols 9999
[x] Ignore case [ ] Ignore full duplicates

mcs: 114 102 313 mcs: 113 337 749 mcs: 113 711 304

[x] Number of symbols 9999
[ ] Ignore case [ ] Ignore full duplicates

mcs: 71 265 632 mcs: 71 347 022 mcs: 71 511 540

[x] Number of symbols 9999
[x] Ignore case [x] Ignore full duplicates

mcs: 106 719 071 mcs: 105 766 062 mcs: 106 050 16
Автор: Angel_Ka
Дата сообщения: 10.05.2016 19:10
shmuz2

Обновил плагин LF Search до версии 3.26.0 и попробовал как он создаёт бранчи.

На тестовой сборке в 714 766 файлов плагин сформировал бранч-панель с 711 946 файлами.
18:27 начат поиск, показатель процесса стоит на 0% и так и будет всё время; счётчик "Найдено файлов:" крутится;
18:31 счётчик застыл на 714766/714766;
18:32 сообщение о ходе поиска сменилось на сообщение об обновлении Временной панели;
18:34 бранч сформирован, в нём 711 946 файлов.

На тестовой сборке, объёмом 1.833.335 файлов, пробовал дважды и оба раза плагин падал.
18:40 начат поиск;
18:42 застыл на 1833335/1833335;
18:50 начато обновление панели;
18:52 исключительная ситуация.

Страницы: 123456789101112

Предыдущая тема: кл


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.