Problems with recursive 'find -exec'

michaelsanford

Translator, Web Developer
I'm trying to make a script that copies all of the .php files in the current folder to files of identical name with .phps as the new extension (i.e., add an "s" to the end of the name). I don't care about overwriting existing .phps files.

I have a feeling it's something like:

find . -name *.php -exec cp $1.s

but I'm not sure about what goes after cp.

Basically I don't know how to pass the filename as an argument to the -exec cp part, then append an "s".

Any ideas? :confused:
 
I haven't used the Darwin command line too much, I'm afraid, but have extensive experience with HPUX.

In HPUX I believe you could do this:

find . -name *.php -exec cp {} {}.s \;

The {} inserts the name of the found file, not $1 (again, this is in HPUX) and I think it can be used any number of times.

Also, for some reason you have to add an escaped semicolon (again, HPUX).


Any or all of this could be meaningless for Darwin...

It also hinges on cp being a program, and not a built-in command, which I'm not sure about...
 
Awesome! I remembered the correct sequence and that line gave it to me. The correct code for Darwin is:

find . -name *.php -exec cp '{}' '{}s' ";"

PS all the standard UNIX commands like cp, mv, cat etc are all applications and not built-in to the environment.

I made it into a script, and then made an alias to the script in .cshrc and it works perfectly.

FYI The application is that I do lots of PHP development, and I like my boss and co-workers to be able to see what's going on, and to take from my script for their workgroup (which is dependent on my PHP). I work straight in my web server folder, so they can see the functionality and the source at any time, and I can test it faster. This also keeps me on my toes, of course ;) Then, deployment is as easy as 1-2-3-f-t-p.

Thanks Brian!
 
Actually, I lied... :confused:

I noticed that it only works if there is only one file that matches the criteria. If there is more than one file (which is the case) it doesn't do any of them, but returns the second file (second alphabetically) and says find: secondfilename.php: unknown option" then dies.

Anyone know what's going on?
 
The answer is simple, what you want is:
find . -name "*.php" -exec cp {} {}s \;

The problem you had was you didn't quote *.php, so what you ended up running was in essance this:
find . -name bar.php blee.php foo.php -exec cp {} {}s \;

This is ofcourse assuming the current working directory only has 3 files with .php endings and they are named bar.php blee.php and foo.php. By not putting the *.php in quotes, you left the globing to be done by the shell, instead of the find command which you wanted to do the globing.

Brian
 
Cool!

Except I've noticed that unless you quote the {} it doesn't work, it just makes a new file called "s" (possibly a concatenation of the others, but my test files are empty).

find . -name "*.php" -exec cp '{}' '{}s' \;
alias phps 'find . -name "*.php" -exec cp "{}" "{}s" \;'

The first line is the one I got working at the prompt, and the second is obviously from .cshrc

Why did I have to quote the {} as well, out of curiosity?

Thanks guys!
 
Back
Top