6

I have ~2000 files in an original naming scheme.

I need to take them all, move the first 4 characters to the end of the filename before the extension, and then add a whitespace before the first 4 characters.

Basically, from:

0123 [UNKNOWN] (Final Fantasy 9) headshot of Freya Crescent {sketch} (ORIGINAL).jpg

to

[UNKNOWN] (Final Fantasy 9) headshot of Freya Crescent {sketch} (ORIGINAL) 0123.jpg
Zanna
  • 70,465

2 Answers2

8

This should work:

rename -n 's/^([0-9]+) (.*)\.jpg/$2 $1.jpg/' /path/to/files/*.jpg

Sample:

0324 [UNKNOWN] (Final Fantasy 9) headshot of Freya Crescent {sketch} (ORIGINAL).txt
0123 [UNKNOWN] (Final Fantasy 9) headshot of Freya Crescent {sketch} (ORIGINAL).txt
0124 [UNKNOWN] (Final Fantasy 9) headshot of Freya Crescent {sketch} (ORIGINAL).txt

Results:

rename(0123 [UNKNOWN] (Final Fantasy 9) headshot of Freya Crescent {sketch} (ORIGINAL).txt,  [UNKNOWN] (Final Fantasy 9) headshot of Freya Crescent {sketch} (ORIGINAL) 0123.txt)
rename(0124 [UNKNOWN] (Final Fantasy 9) headshot of Freya Crescent {sketch} (ORIGINAL).txt,  [UNKNOWN] (Final Fantasy 9) headshot of Freya Crescent {sketch} (ORIGINAL) 0124.txt)
rename(0324 [UNKNOWN] (Final Fantasy 9) headshot of Freya Crescent {sketch} (ORIGINAL).txt,  [UNKNOWN] (Final Fantasy 9) headshot of Freya Crescent {sketch} (ORIGINAL) 0324.txt)

Note: Tested with .txt files will also work on jpg filenames

Information:

([0-9]+): pick the numbers at the front.

(.*): pick every other thing till the file extension.

$2 $1.txt: return the captured groups with the returned group for numbers placed close to the file extension jpg and add a space before the numbers.

-n: run without changing filename so we see what files are changed and what the names are changed to, remove this to rename the files.

George Udosen
  • 36,677
  • Awesome. This works! But my dumb ass forgot to use the -n flag when I was toying with it.

    Is there an easy way to undo what I did with rename 's/^([0-9]+) (.)./$2 $1./' .*

    – mattdawolf Oct 01 '17 at 13:36
  • @mattdawolf Use this rename -n 's/^(.*) ([0-9]*)\.jpg/$2 $1.txt/' *.jpg to reverse what you did. Remeber to leave the -n option and be sure before removing it! – George Udosen Oct 01 '17 at 13:53
  • I corrected the .txt in that but it didn't seem to work. Also what I pasted a few comments up got stripped.

    rename 's/^([0-9]+) (.*)\.*/$2 $1.*/' /path/to/files/*.* is what I ran which gave me this:

    [DanielFox] (character picture) Headshot of Ninetales {digital color} (ELECTRONIC COPY).jpg 0093.*

    – mattdawolf Oct 01 '17 at 14:38
  • @mattdawolf, Is this [DanielFox] (character picture) Headshot of Ninetales {digital color} (ELECTRONIC COPY).jpg 0093.* how your files are now? – George Udosen Oct 01 '17 at 14:49
  • the rest are done properly. It's just this one subdir I messed up. Should've tarred everything but I am low on space. x.x

    Gotta gegt that 0093 back to the start of the file delete all the crap after the extension, do it to the other 500 files, then rerun the script. That will teach me to not back things up...

    – mattdawolf Oct 01 '17 at 15:07
  • @mattdawolf you want the files there named to 0093 [DanielFox] (character picture) Headshot of Ninetales {digital color} (ELECTRONIC COPY).jpg, if so use this rename -n 's/^\.\/(.*)(\.jpg) ([0-9]*)\.\*/$3 $1$2/' ./* Please test before running! And run from the folder in question – George Udosen Oct 01 '17 at 15:13
  • bless you. meh. shoulda stuck coding in high school but the teacher threw me out of that class. All because I objected to the dress code... – mattdawolf Oct 01 '17 at 15:26
1

Use find and Shell Parameter Expansion:

  1. If you don't have rename installed (but most probably it's already installed as part of Perl packages).
  2. You can perform on all or specified matched file patterns "*.jpg" only.
  3. It's recursively as find nature is.
find . -type f -execdir \
    sh -c 'X="[${1#*[}"; Y="${1%% *}"; 
    echo mv -v "$1" "${X%.*} ${Y#./}.${X##*.}"' find-sh '{}' \;

Explanations:

  • X="[${1#*[}" (cut-up-to-first-prefix): This removes everything until first [ seen, and appends [ back to the pattern.

  • Y="${1%% *}" (cut-up-to-last-suffix): This removes everything until last space seen starts from end to the beginning of the filename; This will result ./PATTERN which is ./0123 as example.

  • ${X%.*} (cut-up-to-first-suffix): This removes suffix (ex: .jpg).

  • Y="${Y#./}" (cut-up-to-first-prefix): This removes ./ from variable Y and will result PATTERN only from second step which is 0123 now.

  • .${X##*.}" (cut-up-to-last-prefix): This removes everything until last dot . seen starts from beginning to the end of the filename and append back a dot .; This will result .PATTERN which is .jpg now.

  • -execdir used here to don't result file path by find command and it's safe to intact the /path/to/files/. This will produce a prompt if you have current directory in your PATH or if it contains relative paths which is unsafe.

  • echo is used for dry run, remove it to have actual rename.

αғsнιη
  • 35,660