Friday, January 14, 2011

How to cp file and create directory if not exists?

Hi, all

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 -)
  • Use "dirname" to extract the path "mkdir -p" to create it, something like :

    xargs -d \\n -l '{}' mkdir -p \`dirname '{}'\` && cp '{}' /tmp/xen/
    
    From wazoox
  • 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
    
    From Karolis T.
  • 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.

    From CK
  • 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/
    
    CK : That's the obvious one, but that'll sync everything, not just the modified files, right?
    Kyle Brandt : oops, missed that

0 comments:

Post a Comment