5

I have a folder with more than 5000 images, all with JPG extension.

What i want to do, is to add recursively the "thumb_" prefix to all images.

I found a similar question: Rename Files and Directories (Add Prefix) but i only want to add the prefix to files with the JPG extension.

Community
  • 1
  • 1
MadisonFord
  • 61
  • 1
  • 2
  • 1
    possible duplicate of [Rename Files and Directories (Add Prefix)](http://stackoverflow.com/questions/4787413/rename-files-and-directories-add-prefix), just replace `'*'` with `'*.jpg'`. – Johan May 26 '11 at 14:44
  • no it is not a duplicate. – Abhishek Anand Oct 24 '21 at 15:22

7 Answers7

5

One of possibly solutions:

find . -name '*.jpg' -printf "'%p' '%h/thumb_%f'\n" | xargs -n2  echo mv

Principe: find all needed files, and prepare arguments for the standard mv command.

Notes:

  • arguments for the mv are surrounded by ' for allowing spaces in filenames.
  • The drawback is: this will not works with filenames what are containing ' apostrophe itself, like many mp3 files. If you need moving more strange filenames check bellow.
  • the above command is for dry run (only shows the mv commands with args). For real work remove the echo pretending mv.

ANY filename renaming. In the shell you need a delimiter. The problem is, than the filename (stored in a shell variable) usually can contain the delimiter itself, so:

mv $file $newfile         #will fail, if the filename contains space, TAB or newline
mv "$file" "$newfile"     #will fail, if the any of the filenames contains "

the correct solution are either:

  • prepare a filename with a proper escaping
  • use a scripting language what easuly understands ANY filename

Preparing the correct escaping in bash is possible with it's internal printf and %q formatting directive = print quoted. But this solution is long and boring.

IMHO, the easiest way is using perl and zero padded print0, like next.

find . -name \*.jpg -print0 | perl -MFile::Basename -0nle 'rename $_, dirname($_)."/thumb_".basename($_)'

The above using perl's power to mungle the filenames and finally renames the files.

clt60
  • 62,119
  • 17
  • 107
  • 194
3

In OS X 10.8.5, find does not have the -printf option. The port that contained rename seemed to depend upon a WebkitGTK development package that was taking hours to install.

This one line, recursive file rename script worked for me:

find . -iname "*.jpg"  -print | while read name; do cur_dir=$(dirname "$name"); cur_file=$(basename "$name"); mv "$name" "$cur_dir/thumb_$cur_file"; done

I was actually renaming CakePHP view files with an 'admin_' prefix, to move them all to an admin section.

Brent Self
  • 373
  • 2
  • 5
  • You can always install the `findutils` macport - what contains a gnu-find (command: `gfind`) with `-printf`. – clt60 Jan 14 '14 at 10:33
  • Just noting that I got a file not found error for every line, but it worked as promised – Mars Nov 20 '17 at 05:58
3

Beware of filenames with spaces in (the for ... in ... expression trips over those), and be aware that the result of a find . ... will always start with ./ (and hence try to give you names like thumb_./file.JPG which isn't quite correct).

This is therefore not a trivial thing to get right under all circumstances. The expression I've found to work correctly (with spaces, subdirs and all that) is:

find . -iname \*.JPG -exec bash -c 'mv "$1" "`echo $1 | sed \"s/\(.*\)\//\1\/thumb/\"`"' -- '{}' \;

Even that can fall foul of certain names (with quotes in) ...

FrankH.
  • 17,675
  • 3
  • 44
  • 63
2

You can use that same answer, just use *.jpg, instead of just *.

eduffy
  • 39,140
  • 13
  • 95
  • 92
1

for file in *.JPG; do mv $file thumb_$file; done

if it's multiple directory levels under the current one:

for file in $(find . -name '*.JPG'); do mv $file $(dirname $file)/thumb_$(basename $file); done


proof:
jcomeau@intrepid:/tmp$ mkdir test test/a test/a/b test/a/b/c
jcomeau@intrepid:/tmp$ touch test/a/A.JPG test/a/b/B.JPG test/a/b/c/C.JPG
jcomeau@intrepid:/tmp$ cd test
jcomeau@intrepid:/tmp/test$ for file in $(find . -name '*.JPG'); do mv $file $(dirname $file)/thumb_$(basename $file); done
jcomeau@intrepid:/tmp/test$ find .
.
./a
./a/b
./a/b/thumb_B.JPG
./a/b/c
./a/b/c/thumb_C.JPG
./a/thumb_A.JPG
jcomeau@intrepid:/tmp/test$
jcomeau_ictx
  • 37,688
  • 6
  • 92
  • 107
  • As said in ref. question's answers, you need to consider file names with spaces. – Ashish Patil May 26 '11 at 14:33
  • 1
    @MadisonFord If your files have an extension of .jpg instead of .JPG this will not work on a normal linux environment. Bash is case sensitive, normally. `shopt -s nocaseglob` will turn off case sensitivity. – Spencer Rathbun May 26 '11 at 14:36
  • @MadisonFord, are spaces in filenames a problem in your case? and which command did you paste? – jcomeau_ictx May 26 '11 at 14:39
1

Use rename for this:

rename 's/(\w{1})\.JPG$/thumb_$1\.JPG/' `find . -type f -name *.JPG`
Fredrik Pihl
  • 44,604
  • 7
  • 83
  • 130
-1

For only jpg files in current folder

for f in `ls *.jpg` ; do mv "$f" "PRE_$f" ; done
Ashish Patil
  • 818
  • 7
  • 15