One thing I liked about Linux is it’s hidden simplicity. When in a hurry, I usually go for the first working solution of a given problem. If the same problem appears often, I can get used to the first solution so much that I don’t even think about simplifying it.
A good example of this scenario is recursive renaming of files. It doesn’t happen that often though, but when it does, I am usually in a hurry and use the same old solution that I came across years ago. Here is how I am used to do it:
[me@here dir]$ #Recursively rename some to other [me@here dir]$ for FILE in `find . -name somefile` [me@here dir]> do [me@here dir]> NEW=`echo $FILE | sed -e 's/some/other/'` [me@here dir]> mv "$FILE" "$NEW" [me@here dir]> done
Note that this is more of the base solution. Sometimes I have more parameters to find
. Like when I don’t use sed
at all and just use the -exec mv
syntax. Sometimes I go as far as write a Perl script.
Obviously, this solution is very ineffecient and overdesigned. But it always worked for me.
Today I had to recursively rename a bunch of files and for once I wasn’t in a hurry. While I was slowly enterting in the characters and made a typing mistake, it occured to me that I am overdoing something. So I stopped and made a miniresearch. I spent much less than two minutes on finding a simplier and much nicer way of doing the same.
Apparently, there is a standard utility rename
. It can change the name of the file fully or partially. It needs two parameters – what to change and to what to change it – and a list of file to work with. Here is how it can be used to solve the problem above:
[me@here dir]$ # Recursively rename some to other [me@here dir]$ rename some other `find . -name some`
Now that’s the beauty, isn’t it? It makes me think of all those characters I lost over the years…
Update: edited heavily to remove some nonsense that I typed for no good reason.
Not a shell guy, but using ‘find…’ will split up filenames that have spaces, causing rename to not find the files it returns. Any ideas how to avoid that?
Calling find in this way splits up file names when they have spaces, so:
find . -name "*\?\*" -exec rename 'y/\?/_/' {} \;
will avoid this problem (removing illegal question marks to copy to a fat drive here)
Thanks for the fix, Sam.
I know this is an old post.. but thought you can help.
I have a directory with many sub-dirs, that each have only 1 jpeg file in them and I want to rename them all to “folder.jpg”. The problem is each of the existing jpeg files has a unique name and they also have spaces.
I was thinking about using the sed command in my script, but don’t know how to replace the whole file name and NOT just the extension.
Here is what I have so far.. but its only removing the extension, on my replacement.
find . -name “*.jpg” | while read FILE
do
echo “$FILE”
nfile=`echo $FILE | sed ‘s/\….$/folder.jpg/’`
echo “$nfile”
##mv “$FILE” “$nfile”
done
Do you have any other ideas?
Thanks
rename some other `find . name some`
should be:
rename some other `find . -name some`
Corrected, thanks.
Thanks for the useful Tips youare very helpful
Apparently, there is a standard utility rename. It can change the name of the file fully or partially. It needs two parameters – what to change and to what to change it – and a list of file to work with ,Here is how it can be used to solve the problem above..?
Hi there:
About Sam’s comment, wouldn’t be easier to do:
find . -name “*.PHP” -exec rename -n -v ‘s/.PHP/.php/’ {} \;
I have tried this method and it works fine also over composed file names… or maybe I am missing something. Could you please give an example using Sam’s snippet.
Thanks a lot!!
javier.
Thanks Javier – this worked for me after an hour of trying to find the best option to do this.
FIXED
when working with a computer firm some time ago, I was faced to the same problem and finally wrote a script to recursively rename directories and files.
the initial work was to migrate users documents from a mac OSX server to a windows machine, where many restrictions on file naming apply. the script integrates simple detection of duplicate files (delete if identical or else use alternate name), full logging, progress indicator (we had over 12k files to rename). Users on that network had _really_ bad habits with file naming, so you can be pretty sure it will work for you.
get the script here: http://david.lutolf.net/dt/ulb/#fixnames
find -name “.???*” | rename -n ‘s/\/\./\//’
Example to make hidden files visible (caution: dangerous code)
find -name “.???*” | rename -n ‘s/\/\./\//’
If this fails for you in Ubuntu or one of its derivatives this is because Ubuntu rename is a perl script called prename.
You’ll get an error message
Bareword “old_name” not allowed while “strict subs” in use at (eval 1) line 1.
Instead try
rename ‘s/old_name/new_name/’ `find . -name old_name`
Hope this helps :)