Search code examples
findzsh

Remove parts of filenames that are not floating numbers


I have a directory which contains filenames including IDs in front, e.g:

32.04 Wybrane wzory matematyczne
32.01 Funkcje
31.01 Opracowania lektur EM 2023

The desired filenames after the change would respectively be:

32.04
32.01
31.01

I have other number formats in the directory, such as 30-39, or 31 {filename} so I want to specifically target the files with this floating notation.

The script should run from parent through all its subdirectories.


Solution

  • autoload zmv
    zmv -i '(**/)(<->.<->) *' '$1$2'
    
    • -i - interactive mode; can be removed if you are comfortable with the result.
      The -n (no-op / dry run) option is also available for testing patterns without actually renaming any files.
    • (**/)(<->.<->) * - 'from' pattern.
      • (**/) - recursive glob. Note that in zsh 5.9, the parens are required, even if the component is not referenced in the 'to' pattern.
      • <->.<-> - since <-> is a glob pattern for any number, this will find number.number.
      • * - the rest of the filename.
    • $1$2 - 'to' pattern. $n is the nth parenthesized expression in the 'from' pattern.
      • $1 - from (**/), i.e. the directory part of the full filename, with the trailing /. This will be an empty string for files in the current directory.
      • $2 - from (<->.<->), the floating-point-like number at the start of the filename.

    More about zmv.
    More zmv examples.
    A longer zmv explanation. The description there covers many of the operators used in a previous version of this answer (zmv '(*/)#<->.<-> *' '${f:h}/${${f:t}%% *}').