18

I want to copy modified files in a svn repository to another directory, while keep their directory structure.

After reading awk and xargs manpage I find a way to get changed filenames like this:

$ svn status -q | awk '{ print $2 }' | xargs -d \\n -I '{}' cp '{}' /tmp/xen/

But the problem is that in this way directory structures are not preserved, I want to copy files like this:

./common/superp.c -> /tmp/xen/common/superp.c
./common/m2mgr.c -> /tmp/xen/common/m2mgr.c
./common/page_alloc.c -> /tmp/xen/common/page_alloc.c
./arch/x86/mm.c -> /tmp/xen/arch/x86/mm.c
./arch/x86/mm/shadow/private.h -> /tmp/xen/arch/x86/mm/shadow/private.h

I have tried to change cp command to cp '{}' /tmp/xen/'{}' but it said no such file or directory. Is there any way to make cp copy file and create directory if required? And please point out if this command chain can be simplified. :-)

Thanks for all your replies. Since the directory is a little large, I don't want to copy the whole directory using cp -R or rsync. CK's suggestion of using a tar pipe is quite useful.

svn status -q | awk '{ print $2 }' | xargs tar cf -  | (cd /tmp/xen/; tar xvf -)

7 Answers 7

12

Couple of quick thoughts:

  • Add in a mkdir -p $(dirname FILE)
  • Could you use a tar pipe to sort it all out?

Edit

 tar -cf archive.tar  `svn status -q | awk '{print $2}'`

Should create an archive of the modified files. Then:

  tar -xf archive.tar -C /tmp/xen

should put it where you want. If it needs to be in one step, that's possible too.

5

rsync makes the pretty simple, it the tool I generally use for copying entire directory structures:

rsync -av /home/source/svn/repo /home/dest/svn/

This will create the repo directory and all it contents in the /home/dest/svn directory, so you will have /home/dest/svn/repo/...

So for you example:

rsync -rv ./ /tmp/xen/

-a, would preserve time stamps and be recursive among other things, 'man rsync'.

Update after realizing I read the question wrong:

To mimic the directory structure (tar alternative):

rsync -av --include='*/' --exclude='*' source destination

And then to copy the files before say 20 minutes ago:

find . -type f -mmin -20 -print0 | xargs -0 cp --target-directory /mydestdir/
2
  • That's the obvious one, but that'll sync everything, not just the modified files, right?
    – CK.
    Aug 3, 2009 at 14:25
  • oops, missed that Aug 3, 2009 at 14:29
2

Here's that one-liner for reference:

svn status -q | awk '{print $2}' | xargs tar -c | tar -xC /tmp/xen

And in english:

  • get list of files of interest with svn status -q, which is piped into...
  • awk which extracts the column with the filepaths: awk '{print $2}'
  • xargs is used to give the list of files to tar, which in turn sends a tarball of the files to stdout: xargs tar -c
  • which is promptly re-extracted (-x) into the target directory (-C path): tar -xC /tmp/xen
1

Use "dirname" to extract the path "mkdir -p" to create it, something like :

xargs -d \\n -l '{}' mkdir -p \`dirname '{}'\` && cp '{}' /tmp/xen/
1

rsync -a does not create new directories deeper than in depth 1, so rsync is only partial solution and for example not suitable for me (I googled to find a answer how to rsync directories to some remote hierarchy when several directories are missing in the middle)

Edit: I mean, I have source dir: /home/user/projects/homework/1/1.1/ And I want to rsync it to remote:/home/user/projects/homework/1/1.1/ ...but destination does not have yet directory /home/user/projects/homework ...and I do not want to transfer other subdirectories in the source machine which are in /home/user/projects/

Edit2: Found a way, with rsync --relative option: The above example would go like this:

cd /home/projects/ ; rsync -aR homework/1/1.1 user@remote:/home/user/projects/

0

I'd suggest the following:

  • copy everything
  • find unmodified files and delete those, leaving modified files in their places.

By the way, cp with R flag copies files/folders recursively.

cp -R
0
  • build directory structure into /tmp/f2 for files in /tmp/f

    $ cd /tmp/f/
    $ find . -type f -exec dirname {} \; | uniq | xargs -I {} mkdir /tmp/f2/{} -p
    
  • copy file to new destincation /tmp/f2/

    $ cd /tmp/f
    $ find . -type f -exec cp  {}  /tmp/f2/{} -aPv \;
    

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .