1

I trying to find all files ending with :

  • ancestors-the-humankind-odyssey-trailers-720-1262.mp4
  • high-tech-divers-1080-1234.mp4
  • amazon-divers-720-1323.mp4

and rename this files like this :

  • 720-1262.mp4
  • 1080-1234.mp4
  • 720-1323.mp4

I use regex but nothing, why ? what's wrong pls ?

find . -regex '^.*-(([0-9])*-([0-9])*)\.mp4'

Only one directory and these files, no subdirectories. approximately 300 files .mp4

5
  • Files in one particular directory? Or are these files also in subdirectories? May 7, 2022 at 18:34
  • Approximately how many files are there to search? (10, 1000, 100000,..?) May 7, 2022 at 18:36
  • @roaima Only one directory and these files, no subdirectories. approximately 300 files .mp4
    – Unmecparla
    May 7, 2022 at 18:41
  • Which find implementation are you using? The GNU one?
    – fra-san
    May 7, 2022 at 21:16
  • @fra-san yes GNU findutils
    – Unmecparla
    May 7, 2022 at 21:36

2 Answers 2

1

GNU find supports several regular expression dialects (the -regextype option lets you select one). Parentheses are special characters in some of them and need to be backslash-escaped to gain their special meaning in others.

According to the online documentation, the default dialect used by -regex is "POSIX basic", while the man page available online says the default dialect is "Emacs"1. In both of them parentheses need to be backslash-escaped to work as grouping characters.

These would work:

find . -regex '^.*-\(\([0-9]\)*-\([0-9]\)*\)\.mp4'
find . -regextype posix-extended -regex '^.*-(([0-9])*-([0-9])*)\.mp4'

However, ^ is not needed here (-regex performs a full match on file names) and grouping seems unnecessary; hence

find . -regex '.*-[0-9]*-[0-9]*\.mp4'

should be enough (setting aside the potential issues relating to collation: [0-9] could match more things than [0123456789], depending on your locale).

About renaming: the Perl implementation of rename, if available to you, would be a handy option. Assuming all the files to rename are in the current working directory (no need to find):

perl-rename -nv 's/.*-(\d*-\d*\.mp4)\Z/$1/' -- *

(where \Z is the equivalent of the $ of standard regexps to match at the end of the subject2).

Remove the n (dry-run) option when you feel you are happy with what the command would do.

Note that

  • this will also rename --.mp4 to -.mp4: use \d+ to require at least one digit to appear before and after the last -
  • .* would be needed to also rename hidden files

Alternatively, with GNU find and the standard mv utility (also descending recursively into subdirectories):

find . -regex '.*-[0-9]*-[0-9]*\.mp4' -execdir sh -c '
  for file; do
    toremove=${file%-*-*.mp4}
    echo mv -- "$file" "${file#"$toremove"-}"
  done' mysh {} +

Remove the echo when you feel you are happy with what the command would do.


¹ As Stéphane Chazelas pointed out in comments, a few bug reports have been filed on savannah.org about this inaccuracy/inconsistency in the documentation: https://savannah.gnu.org/bugs/?58384, https://savannah.gnu.org/bugs/?52592, https://savannah.gnu.org/bugs/?61304
² Perl's $ matches at the end of the subject, but also before a newline at the end of the subject, so while fine when working on text lines which may or may not contain a delimiter, it's better to use \Z when working with anything else such as file names here.

2
1

With zsh:

autoload zmv
zmv -n '(**/)*-(<->-<->.mp4)' '$1$2'

(remove the -n for dry-run if happy).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .