Bash rename 360 000 files using find -exec
Solution 1
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/'
Solution 2
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 ;
.
Solution 3
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.
Solution 4
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 {} +
Related videos on Youtube
Comments
-
koubic almost 2 years
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 singlerename
, 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 over 9 yearsIt doesn't really work but it made me remaking the script so now the problem is solved. Thank you.
-
JJoao over 9 years@koubic, successfully remaking your own script is even better than a working suggested solution! What is the problem of this version?
-
koubic over 9 yearsOk, 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 sorename
would be executed severalfold less often. But I eventually used it because speed wasn't a problem on the real server. -
JJoao over 9 years@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!)
-
Alessio over 6 yearsThis, unfortunately, won't work correctly if any of the filenames contain a newline. A workaround is to use
-print0
withfind
for NUL-separated output and runprename
(with full path specified) usingperl -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. -
Jonas Eberle almost 4 yearsThis answer is amazing on so many levels. It includes a "testing" mode and it uses primitive commands.