Renaming/editing a specific part of a file

I am trying to edit rather a lot of files in different directories and finding it such a bore doing it in PyRename.
Filenames such as ‘Clear.and.Present.Danger.1994.1080p.BluRay.x264.YIFY.mp4’
I want to change it so that the year is in ‘()’ but some of the filenames already have the year in brackets or theres a duplicate but in a different format such as ‘.avi’ or ‘.mkv’

I have had a look elsewhere (naughty, I know :wink: )and found this;

and this line in particular…

for file in * ; do mv "$file" "${file//bad/good}" ; done

But I know there’s going to be more involved and it may end up as a script to execute.
I’ve got ‘Linux Pocket Guide’ but it goes nowhere near the stuff I need to do, so I am going to hopefully soon get more books to help me.

if you modify that to

for file in * ; do mv "$file" "${file//1994/(1994)}" ; done

that would work … but only for the current directory … not sub direcories

This will also do subdirectories:

find . -depth -name '*1994*' -execdir bash -c 'for file; do mv -i "$file" "${file//1994/(1994)}"; done' bash {} +

But the problem is, you’d have to do that (and modify it) for every year … on top of that it would also change (1994) to ((1994))

There is no single line command for what you want to do … you’d probably have to get a bit creative with a script.

Now I’ve said that, watch MP come along and prove me wrong with some weird sed command.

Ok, but difficult without a better selection of filenames, but how about this;

find . -exec awk '{ printf "mv %s ",%0;   gsub(".(19|20)...",".(&)."); gsub(".\\(.",".("); gsub(".\\).",")."); print }' {} \;

This will match all files containing .19??. and .20??.
It will then print "mv (original file name) (file name with brackets around the year).
So if you do this command and so “>” , you can then do “chmod a+x; ./” to execute the commands.
(you could stick this last but on the same line as the find, but this way you can look at and make sure it’s going to do what you expect)


echo "" | awk  ....
mv 111.222.333.(2012).xxx

There appears to be a syntax error after the “find” … I get a ton of these:-

mark@AA1-Blue ~/test $ find . -exec awk '{ printf "mv %s ",%0;   gsub(".(19|20).
..",".(&)."); gsub(".\\(.",".("); gsub(".\\).",")."); print }' {} \;
awk: cmd. line:1: { printf "mv %s ",%0;   gsub(".(19|20)...",".(&)."); gsub(".\\
(.",".("); gsub(".\\).",")."); print }
awk: cmd. line:1:                   ^ syntax error

That’s gobbledygook to me so understanding/fixing would be a problem :-[

or am I just being thick here ???

Well I can’t make it “too” easy for you !! … had to leave in the deliberate typo … :wink:

It should be $0, not %0 … :slight_smile:

This is a better calling method …

find . | awk '{ printf "mv %s ",$0;   gsub(".(19|20)...",".(&)."); gsub(".\\(.",".("); gsub(".\\).",")."); print }' 

Here’s the explanation, working without the find (which repeats the command per file);

printf "mv %s", $0"

Print the original filename ($0) with a an “mv” command and no newline.


Replace any occurrence of “.” followed by 19 or 20, followed by any two digits, followed by a dot, with the original match, surrounded by “.( ).”
(the deliberate “bug” here is “.(19|20)…” should probably be “\.(19|20)…\.” - someone can test this … :slight_smile: )


Replace all “.(.” with “.(”


Replace all “.).” with “).”.


Print what’s left.
Simplez … :wink:

Thanks for the help there Mark & MP.
I’ve not got round to executing the command as I’m renaming the files, editing out other spurious rubbish first.
Also, just a thought, remembering back in '91-'92 while on the programming course. I’m sure I remember something about being able to differentiate between numbers and alphabet, so isn’t there some sort of ‘wildcard’ for numbers, separate to alphabet. Can’t we use that in some way?

Just tested it on a couple of files and it produced this result with one of the files;
mv ./Monty Python’s Life of Brian 1979 720p DTS multisub GER HUN HighCode.mkv ./Monty Python’s Life of Brian.(1979)…(20p ).TS multisub GER HUN HighCode.mkv

Notice the 720p changed to (20p ) - Not the desired result.

Also… Where did it put the new file???