IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Commande find + exec pour copie dossiers


Sujet :

Shell et commandes GNU

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Novembre 2009
    Messages : 7
    Points : 4
    Points
    4
    Par défaut Commande find + exec pour copie dossiers
    Bonjour,

    j'ai un dossier contenant des sous-dossiers dont certains sont des archives (contiennent le terme ".arc_" dans leur intitulé).

    |- dossier_source
    |- toto_01092017
    |- fichier1.txt
    |- fichier2.txt
    |- fichier3.txt
    |- toto.arc_01092017
    |- toto_02092017
    |- toto_03092017
    |- toto.arc_03092017
    |- toto_04092017
    |
    |- dossier_cible
    |


    Je souhaiterai copier dans "dossier_cible", les dossiers de "dossier_source" qui ne sont pas des archives.

    J'avais commencé par utiliser la commande ci-dessous :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find /CheminVers/dossier_source -type d ! -name "*.arc_*" -exec cp -r '{}' /CheminVers/dossier_cible \;
    Mais en ajoutant un echo dans le exec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find /CheminVers/dossier_source -type d ! -name "*.arc_*" -exec echo cp -r '{}' /CheminVers/dossier_cible \;
    je me suis aperçue que dans les commandes de copie qui seront exécutées, la première aura pour conséquence de copier tout le contenu du dossier source dans le dossier cible (ce que je ne veux pas). Les autres commandes de copie sont bien celles auxquelles je m'attendais (copie des dossiers ne contenant pas ".arc_").

    Exemple de commandes retournées :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    cp -r /CheminVers/dossier_source /CheminVers/dossier_cible
    cp -r /CheminVers/dossier_source/toto_01092017 /CheminVers/dossier_cible
    cp -r /CheminVers/dossier_source/toto_02092017 /CheminVers/dossier_cible
    [...]
    Pour remédier à ça, j'ai essayé d'ajouter l'option "- mindepth 1". La liste des commandes correspond bien à celle que j'attendais (--> la même liste mais sans la ligne qui copie tout) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    cp -r /CheminVers/dossier_source/toto_01092017 /CheminVers/dossier_cible
    cp -r /CheminVers/dossier_source/toto_02092017 /CheminVers/dossier_cible
    [...]

    Sauf que quand j'exécute la commande (en supprimant le echo du exec), le programme copie le contenu du premier dossier trouvé par le find dans le dossier cible. Cela donne :

    |- dossier_source
    |- toto_01092017
    |- fichier1.txt
    |- fichier2.txt
    |- fichier3.txt
    |- toto.arc_01092017
    |- toto_02092017
    |- toto_03092017
    |- toto.arc_03092017
    |- toto_04092017
    |
    |- dossier_cible
    |- fichier1.txt
    |- fichier2.txt
    |- fichier3.txt
    |- toto.arc_01092017
    |- toto_02092017
    |- toto_03092017
    |- toto.arc_03092017
    |- toto_04092017
    |

    A l'exception du dossier "toto_01092017" pour lequel seuls les fichiers sont copiés à la racine de "dossier_cible", tous les autres dossiers sont correctement copiés donc je me dis que la commande de copie est correctement formée...

    Quelqu'un verrait-il ce qui m'échappe et comment je peux corriger ma commande "find" pour obtenir le résultat escompté (i.e que le dossier "toto_01092017" soit copié mais pas uniquement son contenu) ?

    Je pourrais contourner le problème en redirigeant les lignes de copie dans un fichier dans lequel je supprimerai la première ligne avant d'en exécuter le contenu, mais peut-être quelqu'un saura me dire où est le problème dans ma commande "find"...

    Je vous remercie par avance pour votre aide ou vos conseils.

    Nanou

  2. #2
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Novembre 2009
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    J'ai oublié de préciser que j'ai également essayé la syntaxe ci-dessous, mais j'obtiens le même résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find /CheminVers/dossier_source -mindepth 1 -type d ! -name "*.arc_*" -exec bash -c "cp -r '{}' /CheminVers/dossier_cible" \;
    Nanou

  3. #3
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 101
    Points : 5 849
    Points
    5 849
    Par défaut
    Bonjour Nanou,

    Avec "find", je ne sais pas faire, mais, avec "tar", c'est assez simple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    cd dossier_source; tar --exclude '*.arc_*' -cf . | (cd dossier_cible; tar tvf -) # Pour vérifier...
     
    cd dossier_source; tar --exclude '*.arc_*' -cf . | (cd dossier_cible; tar xvf -) # Pour exécuter...
    Avec un (petit) bug: si le nom d'un fichier (et non un dossier) correspond à '*.arc_*', il ne sera pas copié...

    Au fait, ton "dossier_cible" existe-t-il et est-il bien vide avant de lancer ta commande?

  4. #4
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Novembre 2009
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    Bonjour Jack,

    tout d'abord merci pour ta réponse et ton idée de passer par un tar.

    Ta dernière question m'a aidée à résoudre mon problème.

    Citation Envoyé par jack-ft Voir le message
    Au fait, ton "dossier_cible" existe-t-il et est-il bien vide avant de lancer ta commande?
    Juste avant la copie, dossier_cible était supprimé avant de recevoir les dossiers copiés. La commande "cp" recréait ce dossier (pas de message d'erreur et dossier_cible apparaissait dans mon arborescence), donc je ne me suis pas inquiétée de ce point-là.
    J'ai quand même ajouté une instruction à mon script pour créer explicitement dossier_cible s'il n'existait pas avant l'exécution du "find" et j'ai relancé mon programme de copie : tout est rentré dans l'ordre !

    Merci pour ton aide.
    Nanou

  5. #5
    Nouveau membre du Club Avatar de wh6b.
    Homme Profil pro
    Nicolas Vergnes
    Inscrit en
    Avril 2017
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Nicolas Vergnes
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2017
    Messages : 17
    Points : 33
    Points
    33
    Par défaut
    Bonjour

    je te propose de faire par rsync si l'outil est installé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    rsync -avz --exclude '/*.arc_*'   dossier_source/  dossier_cible/

    Etat initial
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    nico@hk06:~/tmp$ find dossier_*
    dossier_cible
    dossier_source
    dossier_source/toto_04092017
    dossier_source/toto_04092017/fichier1.txt
    dossier_source/toto_04092017/fichier2.txt
    dossier_source/toto_04092017/fichier3.txt
    dossier_source/toto_02092017
    dossier_source/toto_02092017/fichier1.txt
    dossier_source/toto_02092017/fichier2.txt
    dossier_source/toto_02092017/fichier3.txt
    dossier_source/toto.arc_04092017
    dossier_source/toto.arc_04092017/fichier1.txt
    dossier_source/toto.arc_04092017/fichier2.txt
    dossier_source/toto.arc_04092017/fichier3.txt
    dossier_source/toto.arc_01092017
    dossier_source/toto.arc_01092017/fichier1.txt
    dossier_source/toto.arc_01092017/fichier2.txt
    dossier_source/toto.arc_01092017/fichier3.txt
    dossier_source/toto_03092017
    dossier_source/toto_03092017/fichier1.txt
    dossier_source/toto_03092017/fichier2.txt
    dossier_source/toto_03092017/fichier3.txt
    dossier_source/toto_01092017
    dossier_source/toto_01092017/fichier1.txt
    dossier_source/toto_01092017/fichier2.txt
    dossier_source/toto_01092017/fichier3.txt
    On copie ce qui nous interesse
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
     
    nico@hk06:~/tmp$ rsync -avz --exclude '/*.arc_*'   dossier_source/  dossier_cible/
    sending incremental file list
    ./
    toto_01092017/
    toto_01092017/fichier1.txt
    toto_01092017/fichier2.txt
    toto_01092017/fichier3.txt
    toto_02092017/
    toto_02092017/fichier1.txt
    toto_02092017/fichier2.txt
    toto_02092017/fichier3.txt
    toto_03092017/
    toto_03092017/fichier1.txt
    toto_03092017/fichier2.txt
    toto_03092017/fichier3.txt
    toto_04092017/
    toto_04092017/fichier1.txt
    toto_04092017/fichier2.txt
    toto_04092017/fichier3.txt
     
    sent 913 bytes  received 267 bytes  2,360.00 bytes/sec
    total size is 0  speedup is 0.00
    nico@hk06:~/tmp$ find dossier_cible/
    dossier_cible/
    dossier_cible/toto_04092017
    dossier_cible/toto_04092017/fichier1.txt
    dossier_cible/toto_04092017/fichier2.txt
    dossier_cible/toto_04092017/fichier3.txt
    dossier_cible/toto_02092017
    dossier_cible/toto_02092017/fichier1.txt
    dossier_cible/toto_02092017/fichier2.txt
    dossier_cible/toto_02092017/fichier3.txt
    dossier_cible/toto_03092017
    dossier_cible/toto_03092017/fichier1.txt
    dossier_cible/toto_03092017/fichier2.txt
    dossier_cible/toto_03092017/fichier3.txt
    dossier_cible/toto_01092017
    dossier_cible/toto_01092017/fichier1.txt
    dossier_cible/toto_01092017/fichier2.txt
    dossier_cible/toto_01092017/fichier3.txt

    On génère un nouveau sous-dossier à copier et un autre à ne pas copier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    nico@hk06:~/tmp$ cp -r dossier_source/toto_01092017/ dossier_source/toto_05092017
    nico@hk06:~/tmp$ cp -r dossier_source/toto_01092017/ dossier_source/toto.arc_04092017
     
    nico@hk06:~/tmp$ rsync -avz --exclude '/*.arc_*'   dossier_source/  dossier_cible/
    sending incremental file list
    ./
    toto_05092017/
    toto_05092017/fichier1.txt
    toto_05092017/fichier2.txt
    toto_05092017/fichier3.txt
     
    sent 676 bytes  received 88 bytes  1,528.00 bytes/sec
    total size is 0  speedup is 0.00
    Seul ne nouveau sous dossier à copier est pris en compte.


    Seul "inconvénient" que j'y vois :
    - si des choses ont bougé dans des sous-dossiers déjà copiés les modifications de ces fichiers se feront aussi dans les dossier cibles.

  6. #6
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 101
    Points : 5 849
    Points
    5 849
    Par défaut
    Citation Envoyé par nanou_31 Voir le message
    Juste avant la copie, dossier_cible était supprimé avant de recevoir les dossiers copiés. La commande "cp" recréait ce dossier (pas de message d'erreur et dossier_cible apparaissait dans mon arborescence), donc je ne me suis pas inquiétée de ce point-là.
    J'ai quand même ajouté une instruction à mon script pour créer explicitement dossier_cible s'il n'existait pas avant l'exécution du "find" et j'ai relancé mon programme de copie : tout est rentré dans l'ordre !
    C'était bien ce que je soupçonnais!
    Le dossier cible était créé par le premier "cp", ce qui fait que tu as un niveau de moins pour les fichiers copiés par celui-ci.

    L'instruction cp a b n'est pas élémentaire. Elle veut dire (en gros):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Si "b" est un dossier existant
    alors copier "a" à l intérieur du répertoire "b"
    sinon copier "a" en le renommant en "b"
    Je fais partie des gens qui n'aiment pas trop cette double sémantique de "cp" pour plusieurs raisons:
    • Dans la plupart des cas (tous les cas?), le concepteur du programme sait statiquement si "b" existe ou non.
      En fait, je n'ai jamais vu de cas où je ne le savais pas.
      Si quelqu'un a un exemple, j'aimerais bien le voir.
    • Pour moi, la sémantique est différente entre "copier en gardant le nom à l'intérieur de" et "copier en changeant le nom en".
    • La preuve: le résultat obtenu n'est pas le même: il a un niveau de plus lorsque le dossier "b" existe déjà et le nom est changé lorsque "b" n'existe pas.
    • Je préfère les instructions élémentaires qui font clairement, précisément et simplement ce qu'elles font...


    C'est pour cette raison que je préfère ajouter un "/" lorsque je sais que le dossier existe (ou qu'il devrait exister).

    Dans ton cas, si tu avais pris cette précaution, tu aurais tout de suite été alertée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find /CheminVers/dossier_source -mindepth 1 -type d ! -name "*.arc_*" -exec echo cp -r '{}' /CheminVers/dossier_cible/ \;
    Note bien le "/" à la fin de "/CheminVers/dossier_cible/"

    Malheureusement, je n'ai pas trouvé de solution courte pour me protéger dans l'autre sens.

    Si je veux copier "a" en le renommant en "b", l'instruction cp a b ne va pas faire ce que je veux si "b", par malheur, existe déjà...

    La solution que je vois est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if test -d "b"
    then echo "le dossier 'b' ne devrait pas exister" 1>&2; exit 1
    else cp "a" "b"
    fi

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Novembre 2009
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    Bonjour,

    merci wh6b et jack-ft pour vos réponses, vos solutions et vos explications.

    Citation Envoyé par jack-ft Voir le message
    C'était bien ce que je soupçonnais!

    L'instruction cp a b n'est pas élémentaire. Elle veut dire (en gros):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Si "b" est un dossier existant
    alors copier "a" à l intérieur du répertoire "b"
    sinon copier "a" en le renommant en "b"
    J'avais oublié ce détail d'importance !
    Merci à tous les deux pour votre aide.

    Nanou

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Batch] copie dossier vers ftp en ligne de commande
    Par remi82 dans le forum Scripts/Batch
    Réponses: 4
    Dernier message: 24/02/2011, 10h14
  2. commande find -exec fonction ?
    Par slig_80 dans le forum Shell et commandes GNU
    Réponses: 9
    Dernier message: 03/12/2010, 01h39
  3. utilisation de {} dans find -exec et commandes imbriquées
    Par pitipoisson dans le forum Shell et commandes GNU
    Réponses: 12
    Dernier message: 07/09/2009, 11h56
  4. [Système] Commande exec() pour commande système
    Par Antho13 dans le forum Langage
    Réponses: 17
    Dernier message: 09/06/2008, 20h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo