Comment cp fichier et créer un répertoire s'il n'existe pas?

15

Je souhaite copier les fichiers modifiés dans un référentiel svn vers un autre répertoire, tout en conservant leur structure de répertoires.

Après avoir lu la page de manuel awk et xargs, je trouve un moyen d'obtenir des noms de fichiers modifiés comme ceci:

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

Mais le problème est que de cette manière les structures de répertoires ne sont pas conservées, je veux copier des fichiers comme ceci:

./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

J'ai essayé de changer la commande cp en cp '{}' / tmp / xen / '{}' mais elle n'a dit aucun tel fichier ou répertoire. Existe-t-il un moyen de créer un fichier de copie cp et de créer un répertoire si nécessaire? Et veuillez indiquer si cette chaîne de commande peut être simplifiée. :-)

Merci pour toutes vos réponses. Puisque le répertoire est un peu grand, je ne veux pas copier tout le répertoire en utilisant cp -R ou rsync. La suggestion de CK d'utiliser un tuyau de goudron est très utile.

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

Réponses:

12

Quelques réflexions rapides:

  • Ajoutez un mkdir -p $ (dirname FILE)
  • Pourriez-vous utiliser un tuyau de goudron pour tout trier?

Éditer

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

Devrait créer une archive des fichiers modifiés. Alors:

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

devrait le mettre où vous voulez. Si cela doit être en une seule étape, c'est possible aussi.

CK.
la source
4

rsync rend les choses assez simples, c'est l'outil que j'utilise généralement pour copier des structures de répertoires entières:

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

Cela créera le répertoire repo et tout son contenu dans le répertoire / home / dest / svn, vous aurez donc / home / dest / svn / repo / ...

Donc pour vous exemple:

rsync -rv ./ /tmp/xen/

-a, conserverait les horodatages et serait récursif entre autres, 'man rsync'.

Mettre à jour après avoir réalisé que j'ai mal lu la question:

Pour imiter la structure du répertoire (alternative tar):

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

Et puis pour copier les fichiers avant de dire il y a 20 minutes:

find . -type f -mmin -20 -print0 | xargs -0 cp --target-directory /mydestdir/
Kyle Brandt
la source
C'est évident, mais cela synchronisera tout, pas seulement les fichiers modifiés, non?
CK.
oups, j'ai raté ça
Kyle Brandt
2

Voici cette doublure pour référence:

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

Et en anglais:

  • obtenir la liste des fichiers d'intérêt avec svn status -q, qui est canalisée dans ...
  • awk qui extrait la colonne avec les chemins de fichiers: awk '{print $2}'
  • xargs est utilisé pour donner la liste des fichiers à tar, qui à son tour envoie une archive tar des fichiers à stdout: xargs tar -c
  • qui est rapidement ré-extrait ( -x) dans le répertoire cible ( -C path):tar -xC /tmp/xen
Tim Abell
la source
1

Utilisez "dirname" pour extraire le chemin "mkdir -p" pour le créer, quelque chose comme:

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

rsync -a ne crée pas de nouveaux répertoires plus profondément qu'en profondeur 1, donc rsync n'est qu'une solution partielle et par exemple ne me convient pas (j'ai cherché sur google pour trouver une réponse comment rsync des répertoires vers une hiérarchie distante lorsque plusieurs répertoires manquent au milieu )

Edit: Je veux dire, j'ai le répertoire source: /home/user/projects/homework/1/1.1/ Et je veux le resynchroniser à distance: /home/user/projects/homework/1/1.1/ ... mais la destination n'a pas encore de répertoire / home / user / projects / homework ... et je ne veux pas transférer d'autres sous-répertoires dans la machine source qui sont dans / home / user / projects /

Edit2: a trouvé un moyen, avec l'option rsync --relative: l'exemple ci-dessus se présenterait comme suit:

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

zimon
la source
0

Je suggère ce qui suit:

  • tout copier
  • trouver des fichiers non modifiés et les supprimer, laissant les fichiers modifiés à leur place.

Soit dit en passant, cp avec l'indicateur R copie les fichiers / dossiers de manière récursive.

cp -R
Karolis T.
la source
0
  • créer une structure de répertoires /tmp/f2pour les fichiers dans/tmp/f

    $ cd /tmp/f/
    $ find . -type f -exec dirname {} \; | uniq | xargs -I {} mkdir /tmp/f2/{} -p
    
  • copier le fichier dans une nouvelle destination /tmp/f2/

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