Take the 2-minute tour ×
Ask Different is a question and answer site for power users of Apple hardware and software. It's 100% free, no registration required.

I have a whole bunch of files named as following (example):

ADVANTE  18''8.0 PCD5'114.3 ET45 CB73.1.jpg
ADVANTE  18x8.0 PCD6139.7 ET20 CB110.2.jpg
ADVANTE 'A MI576B 20''8.5 PCD6'139.7 ET25 CB110.2 GBXZLDCP.jpg
ADVANTE 'A SH10 15''6.5 PCD8'100-114.3 ET40 CB73.1 3FPBU.jpg

How do I go to each file and change a portion of their filename to:

ADVANTI  18''8.0 PCD5'114.3 ET45 CB73.1.jpg
ADVANTI  18x8.0 PCD6139.7 ET20 CB110.2.jpg
ADVANTI 'A MI576B 20''8.5 PCD6'139.7 ET25 CB110.2 GBXZLDCP.jpg
ADVANTI 'A SH10 15''6.5 PCD8'100-114.3 ET40 CB73.1 3FPBU.jpg

using some sort of command or app? It would take too long to rename each and every one of them manually.

share|improve this question

4 Answers 4

If you use the ZSH shell, this can be done easily in Terminal with zmv (included with OS X by default). Why use fancy scripts if the work is already done?

Type zsh in a terminal window if for some crazy reason you do not have it set as your default shell.

autoload zmv
zmv 'ADVANTE(*)' 'ADVANTI$1'
share|improve this answer
    
Now that is a grade A, excellent reason to fire up zsh. :) +1 –  bmike Feb 27 '13 at 16:33
    
It says localhost% zmv 'ADVANTE(*)' 'ADVANTI$1' zsh: command not found: zmv –  Propeller Feb 28 '13 at 5:11
    
@Propeller Sorry for the late response, missed it the first time. The error means that either you missed the first line (autoload zmv), or you aren't using the stock zsh installation. –  ghoppe Jun 5 at 18:52

In case you need to do this often (and with different file patterns), this perl script might proof very useful. Store the following script as a text file called rename in a convenient place:

#!/usr/bin/perl -w
# rename - Larry's filename fixer
$op = shift or die "Usage: rename expr [files]\n";
chomp(@ARGV = <STDIN>) unless @ARGV;
for (@ARGV) {
    $was = $_;
    eval $op;
    die $@ if $@;
    rename($was,$_) unless $was eq $_;
}

You can then use all the standard perl expressions to rename files, in your case

rename 's/^ADVANTE/ADVANTI/' ADVANTE*
share|improve this answer
1  
make sure the "convenient place" is on your current $PATH, and after saving it you should chmod 755 rename to make it executable. –  MattDMo Feb 27 '13 at 15:00
    
Yeah, that would help indeed :-) –  patrix Feb 27 '13 at 15:52

You can try the commercial app A Better Finder Rename if you want to avoid the Terminal. They also have a free trial.

[Disclaimer: no financial interest in the company which sells ABFR - just a happy customer.]

share|improve this answer

You can use the terminal as follows:

find . -type f -maxdepth 1 -print0 | while read -d $'\0' file; do mv "$file" "$( echo "$file" | sed "s/\.\/ADVANTE/ADVANTI/" )" ; done
  • find is used to list all the files to be renamed
    • . is the directory where to start the search
    • -type f specifies that only files have to be considered
    • -maxdepth 1 specified that find should not recurse on subdirectories
    • -print0 prints the filename followed by an ASCII NUL character (since your file names contain spaces we need a special character to separate them: the space cannot be used)
  • while read -d $'\0' file processes the produced filenames and stores them in the $file variable
  • echo "$file" | sed "s/\.\/ADVANTE/ADVANTI/" performs the substitution (ADVANTE with ADVANTI)
  • mv moves the first file (the original name) to the second one (the one with the substitution)

Tested with:

$ ls -l
total 0
-rw-r--r--  1 corti  corti  0 Feb 27 10:26 ADVANTE  18''8.0 PCD5'114.3 ET45 CB73.1.jpg
-rw-r--r--  1 corti  corti  0 Feb 27 10:26 ADVANTE  18x8.0 PCD6139.7 ET20 CB110.2.jpg
-rw-r--r--  1 corti  corti  0 Feb 27 10:26 ADVANTE 'A MI576B 20''8.5 PCD6'139.7 ET25 CB110.2 GBXZLDCP.jpg
-rw-r--r--  1 corti  corti  0 Feb 27 10:27 ADVANTE 'A SH10 15''6.5 PCD8'100-114.3 ET40 CB73.1 3FPBU.jpg
$ find . -type f -maxdepth 1 -print0 | while read -d $'\0' file; do mv "$file" "$( echo "$file" | sed "s/\.\/ADVANTE/ADVANTI/" )" ; done
$ ls -l
total 0
-rw-r--r--  1 corti  corti  0 Feb 27 10:26 ADVANTI  18''8.0 PCD5'114.3 ET45 CB73.1.jpg
-rw-r--r--  1 corti  corti  0 Feb 27 10:26 ADVANTI  18x8.0 PCD6139.7 ET20 CB110.2.jpg
-rw-r--r--  1 corti  corti  0 Feb 27 10:26 ADVANTI 'A MI576B 20''8.5 PCD6'139.7 ET25 CB110.2 GBXZLDCP.jpg
-rw-r--r--  1 corti  corti  0 Feb 27 10:27 ADVANTI 'A SH10 15''6.5 PCD8'100-114.3 ET40 CB73.1 3FPBU.jpg
share|improve this answer
2  
Is there a specific reason you use find -maxdepth 1 instead of a for f in * loop? –  patrix Feb 27 '13 at 10:08
2  
Yes because of the spaces: * will expand in a list of tokens and the shell will separate them on the spaces. As the list of files contains spaces the shell will not be able to distinguish if the space is part of the name or a separator. –  Matteo Feb 27 '13 at 11:06
1  
Not really, try touch "foo bar" foo; for i in f*; do echo $i; done –  patrix Feb 27 '13 at 17:00
    
@patrix I see but I don't understand why: the man page says that the "list of words following in is expanded". * in this case should be expanded as "foo foo bar" (see echo * | od -abc). Is * expanded differently? –  Matteo Feb 27 '13 at 20:44
    
As far as the shell is concerned, a "word" can contain blanks (because the shell internally doesn't use blanks to separate "words"). It's just if a "word" containing blanks is passed to another (non-shell) command (e.g. od) that the blanks cause problems. –  patrix Mar 4 '13 at 6:13

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.