Use of find command to rename files

findmv

I have a list of 10K mp4 files some of which contains a ? mark. I need to replace these with _ (underscore).

I can use find command to find these files but not sure if I can rename them.

find . -name "*\?*.mp4" -exec mv {} XXXXXXX \;

Looks like I have to iterate through the list returned by find and for each one I need to replace ? with _ but I not sure how to do it.

Best Answer

Don't use find for this - whichever way you go with find you'll need something like a single mv per file. That's a lot of processes, and to no benefit. This is not to mention that it is simply more difficult to do that way. That's my opinion, anyway.

I would use a stream or a batch tool, and tend to prefer pax:

cd -P . && mkdir ../newmp4 &&
pax -rwls'|?|_|g' . "${PWD%/*}/newmp4"

If you can create the directory ../newmp4, that little script will mirror the tree rooted in . to the directory just created with hardlinks, but will have replaced every ? occurring in any filename with an underscore in the meanwhile.

One advantage to this is that both trees continue to exist afterward - none of the dentries rooted in the current directory for those files are affected - they are only altered in the mirrored version of the tree. And so you can inspect the results afterward before deciding which version of the tree to remove. If anything were to go wrong during the operation - there's no harm done.

This does, however, require an fs which supports hardlinks and which has at least as many remaining free inodes as there are child directories of . +2, and assumes that .. . and all children of . share the same filesystem mount.

Practically the same effect might be got with rsync, I think, though I don't believe it is as simply done. If you don't have pax (even if you really should), you can just get it. mirabilos maintains the (to my knowledge) most commonly used version on linux systems.

Related Question