An awesome xargs option and cleaning up SVN accidents
I started using a wonderfully helpful option for xargs recently, after Master Ian showed me its use in a particularly thorny case. Before seeing the cool option, I will give the case as an example of its use:
I am still learning about the best (or even proper) way to use some aspects of SVN. In this particular case, I need to take all the files in a directory that was in the repo, move them into a new directory in the same directory, add another new directory, and copy new files into that.
To better explain the example, here is the structure I had in place, initially:
- Directory 1 (In SVN)
- FilesetA
And this is what I wanted in the end:
- Directory 1
- Directory1.1
- FilesetA
- Directory1.2
- FilesetB
What I should have done is: made the 2 new directories (1.1 and 1.2) within the first one, copied the new files into one (FilesetB), add and commit both new directories and their contents. Then I should have run
1 | svn mv |
on the files in the top directory (FilesetA) into the second new directory.
What I actually did was: created the two new directories, simply
1 | mv |
‘ed FilesetA into one, copied in FilesetB into the other, and then
1 | svn add |
‘ed the two new directories and their contents. Then I had a problem. I still had FilesetA in Directory 1 in the repo, but not locally. So I needed to svn rm those, but I could not since they did not exist locally any more!
In the end, I copied the FilesetA out into a temp directory, when up to the directory above my repository, check the entire thing out again,
1 | svn rm |
‘ed the FilesetA in Directory 1, and then needed to add FilesetA back into Directory 1.1. This was why I moved it to a temp directory. The problem was that that set had several nested directories with
1 | .svn |
directories in them. I had to remove these before adding them into the SVN’ed directories, else mass confusion would result. So I ran:
find . -type d | xargs -I % rm -rf %/.svn
This gem found all directories from the current directory down, and passed them to rm -rf. However, I could not just pipe the results and use xargs, as I needed to append “/.svn” to specify the right directories to remove. This is where -I comes in handy. This option replaces all instances of the string following it with the results of the first command (before the pipe). In this case the string was “%”, for similarity to Python syntax, but any string could be used. The man page uses “replace-str”. So in this particular case, if FilesetA included Directory 1.1.1 and 1.1.2, the command would resolve to: “rm -rf Directory1.1.1/.svn Directory1.1.2/.svn”, which is precisely what was needed!
For some reason, I had a hard time understanding the option from the man page, but Ian translated it to Python for me:
for dir in [find . -type d]: cmd = "rm -rf %s/.svn" % dir os.popen(cmd)
This was much clearer to me. What it basically comes down to is:
OPERATION1 | xargs -I replaceme ANOTHEROPERATION replaceme OTHERTHINGS
translates into
ANOTHEROPERATION OPERATIO1RESULTS OTHERTHINGS
.
Possibly Related (no promises):
- Elegant option checking with optparse
- Recursively ignoring multiple file patterns in subversion
- Useful ways to list directory contents
- Handy Alias: Grab latest svn log
- Useful grep incantations
Related posts brought to you by Yet Another Related Posts Plugin.
August 1, 2007 - 9:31 AM












