0

I managed to find several files with the find command. the files are of the type file_sakfksanf.txt, file_afsjnanfs.pdf, file_afsnjnjans.cpp, now I want to rename them with the rename and -exec command to mywish_sakfksanf.txt, mywish_afsjnanfs.pdf, mywish_afsnjnjans.cpp that only the first prefix is changed. I am trying for some time, so don't blame me for being stupid.

Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
varantir
  • 6,624
  • 6
  • 36
  • 57

2 Answers2

5

If you read through the -exec section of the man pages for find you will come across the {} string that allows you to use the matches as arguments within -exec. This will allow you to use rename on your find matches in the following way:

find . -name 'file_*' -exec rename 's/file_/mywish_/' {} \;

From the manual:

-exec command ;

Execute command; true if 0 status is returned. All following arguments to find are taken to be arguments to the command until an argument consisting of ;' is encountered. The string{}' is replaced by the current file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it is alone, as in some versions of find. Both of these constructions might need to be escaped (with a `\') or quoted to protect them from expansion by the shell. See the EXAMPLES section for examples of the use of the -exec option. The specified command is run once for each matched file. The command is executed in the starting directory.There are unavoidable security problems surrounding use of the -exec action; you should use the -execdir option instead.

Although you asked for a find/exec solution, as Mark Reed suggested, you might want to consider piping your results to xargs. If you do, make sure to use the -print0 option with find and either the -0 or -null option with xargs to avoid unexpected behaviour resulting from whitespace or shell metacharacters appearing in your file names. Also, consider using the + version of -exec (also in the manual) as this is the POSIX spec for find and should therefore be more portable if you are wanting to run your command elsewhere (not always true); it also builds its command line in a way similar to xargs which should result in less invocations of rename.

Community
  • 1
  • 1
tojrobinson
  • 359
  • 2
  • 7
  • It would be more efficient to use either `xargs` or the `+` option to the `find -exec`: `find . -name 'file_*' -exec rename 's/file_/mywish_/' {} +` Then it only runs rename once or a few times, as opposed to once per file. Also, this is assuming a particular rename command syntax, which is system-dependent; it might be `rename file_ mywish_` instead of `rename 's/file_/mywish_/'` – Mark Reed Sep 29 '12 at 18:38
  • @MarkReed: Included mention of the `+` version and an `xargs` alternative. I'm sure the OP can amend the `rename` syntax to conform to their own system if they need to. – tojrobinson Sep 30 '12 at 03:32
0

Don't think there's a way you can do this with just find, you'll need to create a script:

#!/bin/bash
NEW=`echo $1 | sed -e 's/file_/mywish_/'`
mv $1 ${NEW}

THen you can:

find ./ -name 'file_*' -exec my_script {} \;
Jon Lin
  • 142,182
  • 29
  • 220
  • 220