• 31 Posts
  • 21 Comments
Joined 6 years ago
cake
Cake day: January 31st, 2020

help-circle
  • dupeGuru has a great GUI for finding similar looking images (videos are not supported). See How to deduplicate files on Linux with dupeGuru for a tutorial. There’s a similar tool for videos called videoduplicatefinder but I did not try it out.

    I will now share my experiences with using dupeGuru. I ran it in Picture mode and selected “Match pictures of different dimensions”. It was nice to see that it found a few low-quality JPEGs that look identical to higher-quality PNGs. One feature that I really like is the option to “ignore duplicates hardlinking to the same file”; let me explain why: I sometimes download the same image into multiple subfolders of my fan art collection, so I want to keep both images despite them being exact duplicates. This can be accomplished by running rdfind -makehardlinks true . to turn exact duplicates into hardlinks, and running dupeGuru afterwards.

    I experimented a bit with with “Filter Hardness”. On the first run, I set it to “≥95% match” and the results did not contain any false positives! I later went down to “≥70% match”, which reported more duplicates, but also some false positives. If you have many comic doodles in your collection, choose at least 80%. However, if you want to detect crops of other images, you have to choose a lower percentage. On my collection of 3000 images, dupeGuru took about 5 minutes.

    dupeGuru has one major downside: The current release version ignores webp images, but you can build it from source (Arch users can install dupeguru-git from the AUR). Another downside is that it automatically chooses the biggest file among all duplicates as the reference file. This is often a good heuristic but fails badly with webp images that have better compression ratio than other formats. So, if you want to keep only the image of highest quality for every group of duplicates, you have to select it in the GUI and press Ctrl+Space, or export the results to CSV and do some scripting.








  • You can also put this in ~/.config/xkb/symbols/us-custom (create the parent directories if necessary) and set the environment variable XKB_DEFAULT_LAYOUT=us-custom. This works in most Wayland compositors, including river and niri. For Hyprland, you can add this to your config file:

    input {
    	kb_layout = us-custom
    }
    

    If you use GNOME, run

    gsettings set org.gnome.desktop.input-sources mru-sources "[('xkb', 'us-custom')]"
    gsettings set org.gnome.desktop.input-sources sources "[('xkb', 'us-custom')]"
    

    and restart GNOME.


    This is my keyboard layout (I explained some bits of it here):

    default partial alphanumeric_keys
    xkb_symbols "basic" {
    include "us(de_se_fi)" // Umlauts (ä, ö, ü) and €
    
    include "level5(rctrl_switch)"
    
    key.type[Group1] = "EIGHT_LEVEL";
    
    // Number row
    key <TLDE> {[ grave,      asciitilde,  dead_grave,           dead_tilde                                       ]};
    key <AE01> {[ 1,          exclam,      onesuperior,          U2081                                            ]}; // x₁
    key <AE02> {[ 2,          at,          twosuperior,          U2082                                            ]}; // x₂
    key <AE03> {[ 3,          numbersign,  threesuperior,        U2083                                            ]}; // x₃
    key <AE06> {[ 6,          asciicircum, dead_circumflex,      dead_caron                                       ]};
    key <AE08> {[ 8,          asterisk,    enfilledcircbullet,   U22C5,               infinity                    ]}; // dot operator
    key <AE10> {[ 0,          parenright,  NoSymbol,             NoSymbol                                         ]};
    key <AE11> {[ minus,      underscore,  endash,               emdash,              U207B                       ]}; // x⁻
    key <AE12> {[ equal,      plus,        notequal,             approxeq                                         ]};
    
    // Top row
    key <AD01> {[ q,          Q,           NoSymbol,             U211A,               NoSymbol,      NoSymbol     ]}; // ℚ
    key <AD02> {[ w,          W,           NoSymbol,             NoSymbol,            Greek_omega,   Greek_OMEGA  ]};
    key <AD03> {[ e,          E,           NoSymbol,             NoSymbol,            Greek_epsilon, U2203        ]}; // ∃
    key <AD04> {[ r,          R,           NoSymbol,             U211D,               Greek_rho,     U03F1        ]}; // ℝ ϱ
    key <AD05> {[ t,          T,           U03D1,                Greek_tau,           Greek_theta,   Greek_THETA  ]}; // ϑ
    key <AD08> {[ i,          I,           U21d2,                U21d4,               Greek_iota,    integral     ]}; // ⇒ ⇔
    key <AD09> {[ o,          O,           NoSymbol,             NoSymbol,            Greek_omega,   Greek_OMEGA  ]};
    key <AD10> {[ p,          P,           section,              paragraph,           Greek_pi,      Greek_PI     ]};
    
    // Home row
    key <AC01> {[ a,          A,           NoSymbol,             NoSymbol,            Greek_alpha,   U2200        ]}; // ∀
    key <AC02> {[ s,          S,           NoSymbol,             NoSymbol,            Greek_sigma,   Greek_SIGMA  ]};
    key <AC03> {[ d,          D,           NoSymbol,             NoSymbol,            Greek_delta,   Greek_DELTA  ]};
    key <AC04> {[ f,          F,           NoSymbol,             NoSymbol,            Greek_phi,     Greek_PHI    ]};
    key <AC05> {[ g,          G,           degree,               NoSymbol,            Greek_gamma,   Greek_GAMMA  ]};
    key <AC06> {[ h,          H,           U2190,                NoSymbol,            Greek_eta,     U2225        ]}; // ← ∥
    key <AC07> {[ j,          J,           U2193,                NoSymbol,            NoSymbol,      NoSymbol     ]}; // ↓
    key <AC08> {[ k,          K,           U2191,                NoSymbol,            Greek_kappa,   U03F0        ]}; // ↑ ϰ
    key <AC09> {[ l,          L,           U2192,                NoSymbol,            Greek_lambda,  Greek_LAMBDA ]}; // →
    key <AC10> {[ semicolon,  colon,       dead_diaeresis,       NoSymbol,            NoSymbol,      NoSymbol     ]};
    key <AC11> {[ apostrophe, quotedbl,    rightsinglequotemark, NoSymbol,            NoSymbol,      NoSymbol     ]};
    key <AC12> {[ backslash,  bar,         U2500,                U2502,               NoSymbol,      NoSymbol     ]}; // box drawing
    
    // Bottom row
    key <AB01> {[ z,          Z,           NoSymbol,             U2124,               Greek_zeta,    U2220        ]}; // ℤ ∠
    key <AB02> {[ x,          X,           multiply,             NoSymbol,            Greek_xi,      Greek_XI     ]};
    key <AB03> {[ c,          C,           NoSymbol,             U2102,               Greek_chi,     copyright    ]}; // ℂ
    key <AB04> {[ v,          V,           doublelowquotemark,   singlelowquotemark,  Greek_psi,     Greek_PSI    ]};
    key <AB05> {[ b,          B,           leftdoublequotemark,  leftsinglequotemark, Greek_beta,    NoSymbol     ]};
    key <AB06> {[ n,          N,           rightdoublequotemark, rightsinglequotemark,Greek_nu,      U2115        ]}; // ℕ
    key <AB07> {[ m,          M,           U2212,                plusminus,           Greek_mu,      NoSymbol     ]}; // minus
    key <AB08> {[ comma,      less,        dead_cedilla,         NoSymbol,            U27e8,         NoSymbol     ]}; // ⟨
    key <AB09> {[ period,     greater,     ellipsis,             dead_abovedot,       U27e9,         NoSymbol     ]}; // ⟩
    key <AB10> {[ slash,      question,    division,             questiondown,        NoSymbol,      NoSymbol     ]};
    };
    

    GNOME Settings shows a visual preview of the first four layers:

    See also this writeup by Leon Plickat.






  • #!/bin/sh
    # Select a file with fzf from a database sorted by frecency and open it using
    # xdg-open. frece can be found at https://github.com/YodaEmbedding/frece
    
    DB_FILE=${FRECE_FILES_DB:-$HOME/.cache/frecent-files.csv}
    item=$(frece print "$DB_FILE" | fzf --tiebreak=index --scheme=path)
    
    [ -z "$item" ] &amp;&amp; exit 1
    frece increment "$DB_FILE" "$item"
    
    xdg-open "$item"
    
    #!/bin/sh
    # Update frece database
    
    DB_FILE=${FRECE_FILES_DB:-$HOME/.cache/frecent-files.csv}
    tmp_file=$(mktemp)
    fd -H . ~ > "$tmp_file"  # use ~/.fdignore file to exclude certain dirs
    frece update "$DB_FILE" "$tmp_file" --purge-old
    rm "$tmp_file"