Finding files matching a set of conditions

The shell command to find files matching certain conditions is called, unsurprisingly, find, a powerful command. It includes 'actions' which can be performed on the found files. The command below finds all the files we want to copy and ignores the rest.

find DIR_FROM \! \( -path "*/.svn/*" -or -name ".svn" \) -print

It breaks down as

find DIR_FROM

run the find command, searching in DIR_FROM (in OS X, you can just drag DIR_FROM from the Finder to the Terminal window instead of typing it all out)

\!

since we are ignoring files, use ! (negative) to find files which do NOT match the pattern. The slash is needed, because esclamation marks mean something to Terminal, and we want Terminal to ignore that

\(

the parenthesis groups conditions together, since we have more than one. Again, the slash is needed because we want Terminal to ignore its special meaning

-path "/.svn/"

this is the condition "the path includes '/.svn' anywhere in it"

-or

adds conditions together, matching any of them

-name ".svn"

this is the condition "the name of the files is exactly '.svn'

\)

ends the group of condition. The negative ! applies to all of them.

-print

At this stage, just prints the names out on the terminal. Always safe to run this first, to double check the results are as expected.

Delete all .svn directories from a project

In an ideal world, I'd run the find command above with "-print", check it's ok, then I'd run it again with "-copy". Except that there is no "-copy" action, so it's back to man find to work out an action that will help.

It turns out the simplest way is to copy all files first, then find the .svn ones and use the '-delete' action to get rid of them.

this is how you copy a directory in Terminal. cp is the command to copy files on the shell, but it won't do directories. cp -R is used to copy directories. R stands for "recursive", it is common to many other shell commands

find DIR_TO ( -path "/.svn/" -or -name ".svn" )

almost as before - but note there is no ! this time. That's because we want to find the files we don't need, rather than ignore them.

-delete

deletes the files it finds. I suggest to try it with -print first, just to double check

The above works fine, but read on for another way of doing it.

Finding files and passimg them to the cp command

My initial approach when trying to move files across was to use find with the '-exec' action and the cp command, like this:

This looks good at first, but there's a problem - it finds and copies the files, but it doesn't preserve the directory structure, and the files end up all in the same directory. Apparently on Linux you can tell cp to preserve the directory structure with the -b --parent option, but this doesn't work on OS X.

Using cpio to copy files

cpio is an archiving utility similar to tar, but it has an important difference - it can copy files into and archive and then out again to a different location, without actually creating an archive in between. In other words, it copies directory structures. The only snag is that you have to cd to the directory where you are copying from.