Compare files names only, without extension and prefix

Here you can discuss any topic concerning Far macro commands.
KlepetoX
Posts: 102
Joined: Sun 08 Jan, 2012 08:23
Location: Czech Republic

Compare files names only, without extension and prefix

Post by KlepetoX » Mon 01 Dec, 2014 19:06

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: 5227
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 16 times
Been thanked: 151 times

Compare files names only, without extension and prefix

Post by Shmuel » Tue 02 Dec, 2014 00:42

KlepetoX wrote: Will anybody help?
What kind of help do you need? Did you try to write this macro yourself?

KlepetoX
Posts: 102
Joined: Sun 08 Jan, 2012 08:23
Location: Czech Republic

Compare files names only, without extension and prefix

Post by KlepetoX » Tue 02 Dec, 2014 19:35

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: 5227
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 16 times
Been thanked: 151 times

Compare files names only, without extension and prefix

Post by Shmuel » Tue 02 Dec, 2014 23:06

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: 5227
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 16 times
Been thanked: 151 times

Compare files names only, without extension and prefix

Post by Shmuel » Wed 03 Dec, 2014 11:27

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: 102
Joined: Sun 08 Jan, 2012 08:23
Location: Czech Republic

Compare files names only, without extension and prefix

Post by KlepetoX » Thu 04 Dec, 2014 19:25

Thank you, Shmuel, it works best this way

KlepetoX
Posts: 102
Joined: Sun 08 Jan, 2012 08:23
Location: Czech Republic

Compare files names only, without extension and prefix

Post by KlepetoX » Thu 11 Dec, 2014 10:26

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: 11390
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 17 times
Been thanked: 101 times

Compare files names only, without extension and prefix

Post by John Doe » Thu 11 Dec, 2014 10:32

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: 102
Joined: Sun 08 Jan, 2012 08:23
Location: Czech Republic

Compare files names only, without extension and prefix

Post by KlepetoX » Thu 11 Dec, 2014 11:31

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: 11390
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 17 times
Been thanked: 101 times

Compare files names only, without extension and prefix

Post by John Doe » Thu 11 Dec, 2014 11:37

KlepetoX wrote: Compare 20000 files takes one minute or more (large dirs or branch plugin).
Is it much faster without replacement?

KlepetoX
Posts: 102
Joined: Sun 08 Jan, 2012 08:23
Location: Czech Republic

Compare files names only, without extension and prefix

Post by KlepetoX » Thu 11 Dec, 2014 11:49

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: 11390
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 17 times
Been thanked: 101 times

Compare files names only, without extension and prefix

Post by John Doe » Thu 11 Dec, 2014 14:09

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: 102
Joined: Sun 08 Jan, 2012 08:23
Location: Czech Republic

Compare files names only, without extension and prefix

Post by KlepetoX » Thu 11 Dec, 2014 17:35

Now it is really fast. Thanks both of you John Doe and Shmuel.

User avatar
John Doe
Бюрократ
Posts: 11390
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 17 times
Been thanked: 101 times

Post by John Doe » Thu 11 Dec, 2014 18:24

So how fast is it now? Have you done some measurements?

KlepetoX
Posts: 102
Joined: Sun 08 Jan, 2012 08:23
Location: Czech Republic

Compare files names only, without extension and prefix

Post by KlepetoX » Fri 12 Dec, 2014 09:36

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 :-)

KlepetoX
Posts: 102
Joined: Sun 08 Jan, 2012 08:23
Location: Czech Republic

Compare files names only, without extension and prefix

Post by KlepetoX » Sat 02 May, 2015 10:29

I am back with this macro. How to ignore text between brackets? Something like this:

04 My Room (Waiting For Wonderland)

should be the same as

02 My Room

Post Reply

Return to “Macro Commands Discussions”