Add prefix to all images (recursive)
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.
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
pretendingmv
.
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.
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) ...
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.
You can use that same answer, just use *.jpg
, instead of just *
.
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$
Use rename
for this:
rename 's/(\w{1})\.JPG$/thumb_$1\.JPG/' `find . -type f -name *.JPG`
For only jpg
files in current folder
for f in `ls *.jpg` ; do mv "$f" "PRE_$f" ; done
精彩评论