Forum Programmation.shell Linux copy à partir d'une liste de fichiers vers des sous-répertoires à partir d'une liste aussi

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
0
27
sept.
2021

Bonjour,
JE solicite votre aide pour résoudre mon problème car je suis bloquée.
Je vous explique la situation: je souhaite copier des fichiers dont j'ai le chemin sur un fichier txt dans des sous répertoires spécifiques spécifiés dans un second fichier (J'ai aussi un fichier csv complet comprenant ces 2 colonnes: nom des sous-répertoire ($valeur1), chemin du fichier ($valeur2))
J'ai pu créer automatiquement les sous-répertoires en utilisant cette commande:
xargs mkdir -p </scripts/repertoires.csv

Je sais copier tous les fichiers dans un répertoire unique en utilisant cette commande:
cat /scripts/fichiers.csv | xargs -I % cp % /dossierdestination

Mais je n'arrive pas à copier chaque ligne correspondant à un fichier dans le sous répertoire qui lui convient,
Pour essayer d'être + claire je veux copier $valeur2 dans /dossierdestination/$valeur1

Pourriez vous m'aider?

  • # Idées…

    Posté par  (site web personnel) . Évalué à 2.

    Dans un moteur de recherche, regarde les possibilités de faire une boucle qui permette de parcourir deux variables (dans lesquelles tu aurais lu les fichiers) en même temps.

    Ou sinon, créer un 3ème fichier qui concatène le contenu de chaque ligne des deux premiers, puis une boucle sur les lignes du fichier résultant avec un découpage par item ("colonne").

    Python 3 - Apprendre à programmer dans l'écosystème Python → https://www.dunod.com/EAN/9782100809141

  • # UUOC

    Posté par  . Évalué à 1. Dernière modification le 27 septembre 2021 à 22:47.

    cat /scripts/fichiers.csv | xargs -I % cp % /dossierdestination
    
    

    Pourrait êtree remplacé par un truc du genre xargs -I % cp % /dossierdestination < /scripts/fichiers.csv

    Sinon, pour affecter une (ou des) variable a partir de valeurs lues d'un fichier, tu peux utiliser read ..

    Exemple avec le fichier csv ci-dessous :

    totof@superbipbip:~/tmp/essai$ cat test1.csv
    a b c
    d e f
    

    Sinon awk permet de faire des trucs intéressants, mais peut-être pas adapté pour une débutante.

    totof@superbipbip:~/tmp/essai$ while read x y z
    > do
    >  echo "x: ${x}, y: ${y}, z: ${z}"
    > done < test1.csv
    x: a, y: b, z: c
    x: d, y: e, z: f
  • # s/cat/cut/ ?

    Posté par  (site web personnel, Mastodon) . Évalué à 2.

    (J'ai aussi un fichier csv complet comprenant ces 2 colonnes: nom des sous-répertoire ($valeur1), chemin du fichier ($valeur2))

    Donc tu as un fichier composé de lignes de la forme

    $valeur1$delimiteur$valeur2

    Du coup, je supposes que tu as du récupérer la liste des $valeur1 dans un autre fichier

    J'ai pu créer automatiquement les sous-répertoires en utilisant cette commande:
    xargs mkdir -p </scripts/repertoires.csv

    Tu pouvais directement opérer depuis ton fichier initial ainsi (non testé)

    cut -f 1 -d "$delimiteur" | xargs mkdir -p

    Le seul hic/piège est que tes $valeur1 ne doivent pas comporter d'espace (il y a d'autres caractères spéciaux mais les blancs sont les trucs le plus courant/fréquent auquel il faut penser) ; je n'insiste pas dessus vu que tu a déjà fait le boulot en créant un fichier /scripts/repertoires.csv qui convient (la problématique est la même en fait, mais le problème a du ne pas se présenter ou est déjà traité.)

    On peut utiliser la même approche pour l'autre partie du problème

    je souhaite copier des fichiers dont j'ai le chemin sur un fichier txt dans des sous répertoires spécifiques spécifiés dans un second fichier

    Tu peux utiliser aussi le fichier comme tu l'avais déjà fait pour les répertoires, ou utiliser le CSV comme je viens de l'indiquer

    cat /scripts/liste.txt | xargs cp % /dossierdestination
     # ou
    cut -f 2 -d "$delimiteur" | xargs cp % /dossierdestination

    Avec les mêmes précautions déjà évoquées.

    “It is seldom that liberty of any kind is lost all at once.” ― David Hume

    • [^] # Re: s/cat/cut/ ?

      Posté par  (site web personnel, Mastodon) . Évalué à 2. Dernière modification le 28 septembre 2021 à 04:41.

      Arf, pas ien lu jusqu'à la fin

      Je sais copier tous les fichiers dans un répertoire unique en utilisant cette commande:
      cat /scripts/fichiers.csv | xargs -I % cp % /dossierdestination

      Mais je n'arrive pas à copier chaque ligne correspondant à un fichier dans le sous répertoire qui lui convient,
      Pour essayer d'être + claire je veux copier $valeur2 dans /dossierdestination/$valeur1

      Y-a-t-il des caractères problématiques avant et après les valeurs ? Peut-être quelque chose comme

      cat /scripts/fichiers.cvs | xargs -I /%/ cp % dossierdestination

      Sinon boucler sur le fichier…

      cat /scripts/fichiers.csv | while read d f; do
      cp $f /dossierdestination/$d
      done

      ou encore, si tu veux regarder du côté de AWK

      awk '{system(sprintf("cp %s dossierdestination/%s\n", $2, $1));}' /scripts/fichiers.csv

      “It is seldom that liberty of any kind is lost all at once.” ― David Hume

  • # "… un fichier csv complet comprenant ces 2 colonnes …"

    Posté par  . Évalué à 3.

    Bonjour

    doudou31 a écrit :

    … J'ai aussi un fichier csv complet comprenant ces 2 colonnes: nom des sous-répertoire ($valeur1), chemin du fichier ($valeur2) …

    J'aimerai bien voir quelques lignes de ce fichier, avec, pour chaque ligne,
    la ligne de commande(s) que tu voudrais lancer en fonction du contenu de chaque ligne,
    ça me permettrait de voir comment se présentent les données et ce que tu voudrais en faire.

  • # essais infructueux

    Posté par  . Évalué à 1.

    Tout d'abord merci pour vos réponses, ça me fait chaud au coeur :) et je me dis que cela va finir par marcher… bientôt :)

    Voici 2 lignes d'exemple du fichier csv qui contient les 2 valeurs, délimitées par ; :
    LV0AD1-790;2021/21H83UVS/LV0AD1-790 IT1/C_21H83UVS_48079_413_20210430-113018_DUA.pdf
    LV0BD1-790;2021/21H83UVS/LV0BD1-790 ITA 3/C_21H83UVS_48084_413_20210430-110347_DUB.pdf

    correspondant à $d/$f et où $f a parfois des espaces qu'il faut prendre en compte.

    Ce que je voudrais c'est copier chaque $f dans son sous répertoire rep_destination/$d/. ,en résumé ça pourrait ressembler à ça : cp $f rep_destination/$d/.

    J'ai essayé notamment avec vos préconisations:
    cat /scripts/demandes_VES_complet.csv | while read d f; do cp $f /admin_VES_2021/$d/; done
    Mais sans succes: cp: opérande de fichier cible manquant après '/admin_VES_2021/CN01L2-790;2021/21SFZNC1/CN01L2-790/C_21SFZNC1_45680_413_20210427-212308.pdf/'

    • [^] # Re: essais infructueux

      Posté par  . Évalué à 4.

      Hello.
      Au vu du resultat de ta derniere commande, je pense qu'il te manque juste un IFS=';' avant le while.
      Note: il est plus prudent de commencer a faire des echos dans ta boucle, plutot que directement un cp, quand tu en es encore a la mise au point…

      ++
      Gi)

    • [^] # Re: essais infructueux

      Posté par  . Évalué à 3.

      exec 3< fictest.csv
      while read -u 3 ligne 
      do
          rep=${ligne%;*}
          fic=${ligne#*;}
          cp "$fic" $rep
      done
      
  • # Top! merci énormément

    Posté par  . Évalué à 2.

    Vous l'aurez compris en voyant le titre, la solution ci dessous à fonctionné :
    exec 3< fictest.csv
    while read -u 3 ligne
    do
    rep=${ligne%;}
    fic=${ligne#
    ;}
    cp "$fic" $rep
    done

    Par contre celle ci ne fonctionne pas pour copier les fichiers dont le chemin comprend un espace:
    cat scripts/demandes_VES_complet.csv | while IFS=';' read d f; do cp $f /admin_VES_2021/$d/; done

    En tout cas merci pour votre aide , vous êtes super

    • [^] # Re: Top! merci énormément

      Posté par  . Évalué à 2. Dernière modification le 28 septembre 2021 à 14:46.

      Bonjour

      … Par contre celle ci ne fonctionne pas pour copier les fichiers dont le chemin comprend un espace: …

      Si le fichier à traiter est nommé fictest.csv
      essaye avec ça :

      while read ligne 
      do
          rep="${ligne%;*}"
          fic="${ligne#*;}"
          cp "$fic" "$rep"
      done < fictest.csv
      
    • [^] # Re: Top! merci énormément

      Posté par  (site web personnel) . Évalué à 4.

      Deux petites choses :

      • mieux vaut utiliser le bouton Répondre que de créer un nouveau commentaire. C'est plus lisible.
      • pour ne pas avoir de problème en bash, toujours quoter, c’est-à-dire entourer de guillemets les variables. https://tldp.org/LDP/abs/html/quotingvar.html

      « Il vaut mieux mobiliser son intelligence sur des conneries que mobiliser sa connerie sur des choses intelligentes. »

  • # Donc, finalement, ça peut être :

    Posté par  . Évalué à 2.

    IFS=";"               # le séparateur dans le fichier d'entrée est ";"
    while read REP FIC    # la variable REP reçoit le 1er champ lu, et FIC le 2ème
    do
        cp "$FIC" "$REP"
    done < lefichier.csv
    

    Adaptable à toute lecture de fichier csv.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.