Compare files names only, without extension and prefix

Here you can discuss any topic concerning Far macro commands.
KlepetoX
Posts: 129
Joined: Sun 08 Jan, 2012 08:23
Location: Czech Republic
Has thanked: 2 times
Been thanked: 1 time

Compare files names only, without extension and prefix

Post by KlepetoX »

I need macro that compares files on both panels without extensions and prefix (after first space in filename) - filenames only. Example:

Code: Select all


The same (will be selected):

03 Forgotten Hopes.flac  |  06 Forgotten Hopes.mp3
1-14 Transacoustic.mp3   |  05 Transacoustic.ape
06 One Last Goodbye.mp3  |  2-05 One Last Goodbye.mp3
Will anybody help?
Shmuel
Posts: 6815
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 526 times

Compare files names only, without extension and prefix

Post by Shmuel »

KlepetoX wrote: Will anybody help?
What kind of help do you need? Did you try to write this macro yourself?
KlepetoX
Posts: 129
Joined: Sun 08 Jan, 2012 08:23
Location: Czech Republic
Has thanked: 2 times
Been thanked: 1 time

Compare files names only, without extension and prefix

Post by KlepetoX »

I finally did it. It may be useful for somebody. Shmuel, please see if something should be done better. I am an common user only, not programmer or macro "writer" :-)

Code: Select all

Macro {
  key="ShiftDivide";
  area="Shell Search";
  description="Select files with the same names without numeric prefix and extension";
  condition=function()
    return APanel.Visible and PPanel.Visible and not APanel.Empty and not PPanel.Empty
  end;
  action=function()
    Panel.Select(0,0) Panel.Select(1,0)    -- deselect first
    local ia,ip                            -- cycle counters for active/passive panel
    local AName,PName,ANameOnly,PNameOnly  -- file name in active/passive panel, file name in a/p panel without prefix and ext.
    local i,j                              -- cycle counters for filename scan (searching for first alpha char.)
    local s,t                              -- character from filename, if it is alpha char., do action and break cycle
    for ia=1,APanel.ItemCount do
        AName=mf.fsplit(Panel.Item(0,ia,0),0x4) -- name without extension
        for i=0,mf.len(AName) do
            s=mf.substr(AName,i,1)
            i=i+1
            if far.LIsAlpha(s) then ANameOnly=mf.substr(AName,i-1)
               for ip=1,PPanel.ItemCount do
                   PName=mf.fsplit(Panel.Item(1,ip,0),0x4)
                   for j=0,mf.len(PName) do
                       t=mf.substr(PName,j,1)
                       j=j+1
                       if far.LIsAlpha(t) then PNameOnly=mf.substr(PName,j-1) break else PNameOnly='' end
                   end
                   if ANameOnly:upper()==PNameOnly:upper() then Panel.Select(0,1,1,ia) Panel.Select(1,1,1,ip) end
               end
               break
            end
        end
    end;
  end;
}

Shmuel
Posts: 6815
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 526 times

Compare files names only, without extension and prefix

Post by Shmuel »

KlepetoX wrote: I finally did it.
And I'm very glad you did it!
Here is a somewhat shorter version of your macro:
Shmuel
Posts: 6815
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 526 times

Compare files names only, without extension and prefix

Post by Shmuel »

Here is a variant optimized for speed.
Tested on the System32 directory shown in both panels (2700 files and folders).
Not optimized version: 55000 msec
Optimized version: 160 msec
KlepetoX
Posts: 129
Joined: Sun 08 Jan, 2012 08:23
Location: Czech Republic
Has thanked: 2 times
Been thanked: 1 time

Compare files names only, without extension and prefix

Post by KlepetoX »

Thank you, Shmuel, it works best this way
KlepetoX
Posts: 129
Joined: Sun 08 Jan, 2012 08:23
Location: Czech Republic
Has thanked: 2 times
Been thanked: 1 time

Compare files names only, without extension and prefix

Post by KlepetoX »

I have edited macro trying to ignore some more charecters than prefix and extension only. I have tried mf.replace, regex.gsub and :gsub. Each of them is slow, is there another faster possibility?

Code: Select all

Macro {
  key			="ShiftDivide";
  area			="Shell Search";
  description	="Select files with the same names without numeric prefix and extension";
  condition=function()
    return APanel.Visible and PPanel.Visible and not APanel.Empty and not PPanel.Empty
  end;
  action=function()
    Panel.Select(0,0) Panel.Select(1,0)  -- deselect first
    local PTable={}
    for ip=1,PPanel.ItemCount do
      local PNameOnly=mf.fsplit(Panel.Item(1,ip,0),0x4):match("%a.*")  -- name without extension
      if PNameOnly then
        PNameOnly=mf.replace(PNameOnly,"[ _-.,!']",'')   -- fastest
--        PNameOnly=regex.gsub(PNameOnly,"[ _-.,!']",'') -- slower
--        PNameOnly:gsub("[ _-.,!']",'')                 -- slowest
        PNameOnly=PNameOnly:upper()
        PNameOnly=mf.replace(PNameOnly,'THE ','')
        PTable[ip]=PNameOnly
      end
    end
    for ia=1,APanel.ItemCount do
      local ANameOnly=mf.fsplit(Panel.Item(0,ia,0),0x4):match("%a.*")
      if ANameOnly then
        ANameOnly=mf.replace(ANameOnly,"[ _-.,!']",'')
--        ANameOnly=regex.gsub(ANameOnly,"[ _-.,!']",'')
--        ANameOnly:gsub("[ _-.,!']",'')
        ANameOnly=ANameOnly:upper()
        ANameOnly=mf.replace(ANameOnly,'THE ','')
        for ip,PNameOnly in pairs(PTable) do
          if ANameOnly==PNameOnly then
            panel.SetSelection(nil,0,ip,true)
            panel.SetSelection(nil,1,ia,true)
          end
        end
      end
    end
    panel.RedrawPanel(nil,0)
    panel.RedrawPanel(nil,1)
  end;
}

User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

Compare files names only, without extension and prefix

Post by John Doe »

KlepetoX wrote: PNameOnly=mf.replace(PNameOnly,"[ _-.,!']",'')   -- fastest
Does it really work for you?
I doubt, because it is not intended to process regexps.
KlepetoX wrote: Each of them is slow
It is unusual.
Please define your meaning for "slow".
KlepetoX
Posts: 129
Joined: Sun 08 Jan, 2012 08:23
Location: Czech Republic
Has thanked: 2 times
Been thanked: 1 time

Compare files names only, without extension and prefix

Post by KlepetoX »

Does it really work for you?
I doubt, because it is not intended to process regexps.
Indeed, doesn't work at all...
Please define your meaning for "slow".
Compare 20000 files takes one minute or more (large dirs or branch plugin). In small directories it is ok.
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

Compare files names only, without extension and prefix

Post by John Doe »

KlepetoX wrote: Compare 20000 files takes one minute or more (large dirs or branch plugin).
Is it much faster without replacement?
KlepetoX
Posts: 129
Joined: Sun 08 Jan, 2012 08:23
Location: Czech Republic
Has thanked: 2 times
Been thanked: 1 time

Compare files names only, without extension and prefix

Post by KlepetoX »

You are right, not much. Speed of comparing in common directories is sufficient enough, it was only test where it seems slow, common folders haven't 20000 files :-)
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

Compare files names only, without extension and prefix

Post by John Doe »

A bit more optimization:

Code: Select all

local function norm(name)
  name = mf.fsplit(name,0x4):match("%a.*")
  return name and name:upper() or nil
end

Macro {
  key="ShiftDivide";
  area="Shell Search";
  description="Select files with the same names without numeric prefix and extension";
  condition=function()
    return APanel.Visible and PPanel.Visible and not APanel.Empty and not PPanel.Empty
  end;
  action=function()
    Panel.Select(0,0); Panel.Select(1,0)
    local PTable={}
    for ip=1,PPanel.ItemCount do
      PTable[ip]=norm(Panel.Item(1,ip,0))
    end
    local a,p = {},{}
    for ia=1,APanel.ItemCount do
      local ANameOnly=norm(Panel.Item(0,ia,0))
      if ANameOnly then
        for ip,PNameOnly in pairs(PTable) do
          if ANameOnly==PNameOnly then
            a[#a+1],p[#p+1] = ia, ip
          end
        end
      end
    end
    panel.SetSelection(nil,0,p,true)
    panel.SetSelection(nil,1,a,true)
    panel.RedrawPanel(nil,0)
    panel.RedrawPanel(nil,1)
  end;
}
KlepetoX
Posts: 129
Joined: Sun 08 Jan, 2012 08:23
Location: Czech Republic
Has thanked: 2 times
Been thanked: 1 time

Compare files names only, without extension and prefix

Post by KlepetoX »

Now it is really fast. Thanks both of you John Doe and Shmuel.
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

Post by John Doe »

So how fast is it now? Have you done some measurements?
KlepetoX
Posts: 129
Joined: Sun 08 Jan, 2012 08:23
Location: Czech Republic
Has thanked: 2 times
Been thanked: 1 time

Compare files names only, without extension and prefix

Post by KlepetoX »

Yes, I have done measurements right now. Here is result:

Left panel: 11398 files
Right panel: 11391 files

After running macro:
Left panel: 11255 files selected
Right panel: 11252 files selected

Time:
Old macro: 32 seconds
Now with John Doe's macro: 3 seconds

Great work :-)
Post Reply

Return to “Macro Commands Discussions”