开发者

Add prefix to all images (recursive)

开发者 https://www.devze.com 2023-03-08 09:10 出处:网络
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 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 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.


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
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号