3

I've got around 360 000 files like:

./001/1/1.jpg
./001/1/2.jpg
./001/2/1.jpg
./002/1/1.jpg
./003/1/1.jpg
...
pattern: [60 dirs]/[1000 subdirs]/[4-10 files].jpg

I want to rename files using rename for example from *.jpg to *.jpeg. I can't do it with single rename, because I get the error argument list is too long.

Searching for solution, I figured out this, but it renames nothing:

find -maxdepth 2 -mindepth 2 -type d -exec rename -n 's/jpg/jpeg/' {}/* \;

When I check if the {} is expanded replacing rename with echo:

find -maxdepth 2 -mindepth 2 -type d -exec echo "rename -n 's/jpg/jpeg/' {}/*" \;

I get expected result:

rename -n 's/jpg/jpeg/' ./061/61430/*
rename -n 's/jpg/jpeg/' ./061/61431/*
...

If I run any of these rename commands, I rename works. So the should be problem with the {}.

Thank you for help!

koubic
  • 133
  • 1
  • 5

5 Answers5

4

In the first instance, * is expanded by the shell before it gets to rename (if it is expanded at all - I doubt anything matches {}/*), and if it isn't expanded, the command that is executed is rename with the three arguments -n, s/jpg/jpeg/ and some/path/*. That last argument is not the name of an existing file so rename does nothing.

Without shell globbing, the path is useless to rename.

So, instead, do:

find -maxdepth 3 -mindepth 3 -type f -iname '*.jpg' -exec rename -n 's/jpg$/jpeg/i' {} +

Use find's ability to build command lines as long as is possible with + instead of ;.

muru
  • 72,889
3
find  | prename 's/\.jpg$/.jpeg/'

or if you have oder files in the currunt directory

find 0[0-9][0-9] | prename 's/\.jpg$/.jpeg/'
JJoao
  • 12,170
  • 1
  • 23
  • 45
  • It doesn't really work but it made me remaking the script so now the problem is solved. Thank you. – koubic Jan 06 '15 at 12:32
  • 1
    @koubic, successfully remaking your own script is even better than a working suggested solution! What is the problem of this version? – JJoao Jan 06 '15 at 14:00
  • Ok, I'm sorry, it actually works. It's just a different approach to my original question. Your approach is slower, because rename process has to be run for every single file. My approach wanted to put a subdirectory to rename so rename would be executed severalfold less often. But I eventually used it because speed wasn't a problem on the real server. – koubic Jan 07 '15 at 13:50
  • @koubic, thank you for everything. In my approach, rename process should be executed only once. If you can, it would be interesting to "time" the solutions (I'm curious about the time taken for renaming such a big number of files!) – JJoao Jan 07 '15 at 15:07
  • This, unfortunately, won't work correctly if any of the filenames contain a newline. A workaround is to use -print0 with find for NUL-separated output and run prename (with full path specified) using perl -0 - e.g. find -print0 | perl -0 /usr/bin/prename 's/\.jpg$/.jpeg/'. prename itself should (but doesn't) have a -0 option...I've reported this as a bug to rt-cpan.org. – cas Feb 13 '18 at 23:01
1

You should not specify type d unless you want to rename only directories. To change extensions .jpg to .jpeg try

find . -maxdepth 2 -mindepth 2 -name '*.jpg' -exec sh -c 'echo mv -- "$0" "${0%%.jpg}.jpeg"' {} \;

Remove echo if you like what you see on the screen.

jimmij
  • 47,140
1

Here is an alternative way should rename happen to be missing:

find 0[0-6][0-9] -name "*.jpg" -exec sh -c 'for i do echo mv "$i" "${i%g}eg"; done' sh {} + 
jlliagre
  • 61,204
0

Using cygwin, my version of rename does not have the regex replacement, nor does its rename [options] expression replacement file... syntax seem to work. Also, the bash suggestions fail with

... -c: line 0: unexpected EOF while looking for matching `"'
... -c: line 1: syntax error: unexpected end of file

Alas... there is always perl:

perl -MFile::Find -e 'find(sub{return unless /^(.*)\.jpg$/;`mv $_ $1.jpeg`}, ".")'
Lucas
  • 143
  • The rename mentioned in many of these answers is written in perl. See http://tips.webdesign10.com/files/rename.pl.txt for one implementation. – Chris Davies Jul 01 '16 at 22:27
  • @roaima, how do you know that? On my system (the latest cygwin), the rename found in my default path is "The rename command is part of the util-linux package and is available from ftp://ftp.kernel.org/pub/linux/utils/util-linux/" and is a binary file, not a perl script... – Lucas Jul 03 '16 at 22:58
  • I also have Cygwin on a number of Windows platforms. There are two different implementations of rename and yours as described is the "other" one. – Chris Davies Jul 03 '16 at 23:20