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 :

Traitement d'un fichier csv pour executer une commande shell


Sujet :

Shell et commandes GNU

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 52
    Points : 44
    Points
    44
    Par défaut Traitement d'un fichier csv pour executer une commande shell
    Bonjour,

    Sous linux et shell BASH j’essaie de faire les actions suivantes :

    1: trouver les doublons de fichiers qui porte un nom semblables (pas de vrais doublons, uniquement doublon par un nom proche) avec la même extension (.mm dans ce cas)

    2 lister le resultat de cette recherche dans 1 fichier avec 1 ligne par résultat dans l'ordre alphabétique des noms des fichiers (sans tenir compte des chemins des dossiers)

    3 executer par une commande shell des actions diverses (renomage, suppression, déplacement etc..) sur ce fichier qui aura était expurger par suppression des lignes que je ne veux pas traiter.

    Pour l'action 1
    J'avais trouvé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find ~/Documents/ShellEssais/Doublons -iname "*.mm" -type f  -printf '%s ;%c; ' -exec  /usr/bin/md5sum {}  \; |sed -e 's/ ./;/g'|sort -n -t";" -k1,3 > gros_fichier_doublons.csv
    Qui conviendrait presque mais je ne veux pas trouver les doublons je veux simplement lister par ordre alphabétique les noms de fichiers et les envoyer avec le chemin dans un fichier .csv

    Pour l'action 2
    Je n'arrive pas à trouver l'instruction permettant de changer la forme du résultat de l'extraction obtenu par find. Je n'est pas encore compris comment utiliser printf

    Pour l'action 3
    J'ai trouvé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $ for doublon in `cat doublons.csv ` ; do rm -i $doublon; done
    Mais je rencontre 2 problèmes
    Comment depuis le fichier qui contient les colonnes diverses (inodes, chemins, taille, noms des fichiers) facilement ne retrouver que les noms des fichiers
    et
    Je ne sais pas réaliser le traitement sur les noms de fichiers avec un ou des espaces

    Merci pour votre aide

  2. #2
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 549
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 549
    Points : 19 378
    Points
    19 378
    Par défaut
    Bonjour,

    SUR linux et AVEC bash.

    1. trouver les fichiers qui portent la même extension (.mm dans ce cas)
    Je n'arrive pas à trouver l'instruction permettant de changer la forme du résultat
    printf est la commande la plus adaptée pour ça; il faut lire le man et faire des essais.
    si vraiment tu n'y arrives pas, montre-nous ce que tu as fait, et on t'expliquera.

    J'ai trouvé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $ for doublon in `cat doublons.csv ` ; do rm -i $doublon; done
    non. ->Comment lire un fichier en shell.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  3. #3
    Membre éprouvé Avatar de balkany
    Homme Profil pro
    Touriste
    Inscrit en
    Juillet 2017
    Messages
    346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 346
    Points : 977
    Points
    977
    Par défaut
    Citation Envoyé par philoeil Voir le message
    Mais je rencontre 2 problèmes
    Comment depuis le fichier qui contient les colonnes diverses (inodes, chemins, taille, noms des fichiers) facilement ne retrouver que les noms des fichiers
    et
    Je ne sais pas réaliser le traitement sur les noms de fichiers avec un ou des espaces
    En supposant que la commande qui remplit le fichier .csv n'a pas altéré les noms de fichiers (ce qui serait le cas ici si ces noms contenaient des espaces), et en supposant qu'ils sont bien séparés du reste par un délimiteur connu, comme tu sembles vouloir le faire avec le ;, alors
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk -F ';' '{print $NF}' doublons.csv
    te permettra de retrouver facilement tes noms de fichiers.

    Pour le « traitement sur les noms de fichiers avec un ou des espaces », s'il s'agit bien de ton point 3, il faut que tu mettes des guillemets autour de tes noms de variable bash :

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 52
    Points : 44
    Points
    44
    Par défaut
    Bonjour,

    Merci pour vos réponses "Balkany" et "N'Bah", je manque un peu de temps mais je regarde tout ça et revient vers vous pour les résultats.
    Si une bonne âme veut me faciliter la tache je ne suis pas contre...
    Je risque d'en avoir pour 1 semaine alors merci de votre patience

    Au plaisir de vous lire

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 52
    Points : 44
    Points
    44
    Par défaut
    Bonjour,

    Voilà ou j'en suis

    J'ai commenc par chercher comment améliorer mon étape 1 et 2
    et j'ai trouvé ceci qui fonctionne presque :

    Commande 1 : qui m'apporte les noms des doublons et les dates de création et les inodes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find ~/Documents/ShellEssais/Doublons -iname "*.mm" -type f -printf '%s ;%c; ' -exec ls -R {}  \; >gros7Ini.csv
    Qui me donne pour exemple le résultat suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    47607 ;Sun Sep 22 18:40:54.9364076800 2019; /home/phil/Documents/ShellEssais/Doublons/OrganisationRepertoiresIdeale.mm
    12046 ;Sun Sep 22 15:52:17.3895923870 2019; /home/phil/Documents/ShellEssais/Doublons/Projet U2_4.mm
    47607 ;Mon Sep 23 18:31:45.0243998170 2019; /home/phil/Documents/ShellEssais/Doublons/OrganisationRepertoiresIdeale22.mm
    12046 ;Sun Sep 22 15:52:17.3895923870 2019; /home/phil/Documents/ShellEssais/Doublons/Doublons2/Projet U2_V2.mm
    12046 ;Mon Sep 23 18:32:10.5923920570 2019; /home/phil/Documents/ShellEssais/Doublons/Doublons2/Projet U2_V23.mm
    47607 ;Mon Sep 23 18:31:55.8003965850 2019; /home/phil/Documents/ShellEssais/Doublons/Doublons2/OrganisationRepertoiresIdeale23.mm
    12046 ;Sun Sep 22 15:52:17.3895923870 2019; /home/phil/Documents/ShellEssais/Doublons/Doublons2/Projet U2.mm

    Commande 2 qui me permet de ne plus trouver que les noms des fichiers
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find ~/Documents/ShellEssais/Doublons -iname "*.mm" -type f -printf '%s ;%c; ' -exec ls -R --format=single-column  {} \; |sed -e 's/[^-][^\/]*\//-/g' >gros7simplifié.csv
    Qui me donne pour exemple le résultat suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ------OrganisationRepertoiresIdeale.mm
    ------Projet U2_4.mm
    ------OrganisationRepertoiresIdeale22.mm
    -------Projet U2_V2.mm
    -------Projet U2_V23.mm
    -------OrganisationRepertoiresIdeale23.mm
    -------Projet U2.mm
    Etape suivante :
    Il me faut trouver comment combiner mes 2 commandes
    pour 1 trier par noms de fichier la commande 1
    Pour utiliser le fichier resultat de la commande 1 pour appliquer la commande 2 mais supprimer les "-"

    A la semaine prochaine... to be continued...

    Si vous voulez me suggérer des choses pour me faire progresser plus vite merci...

  6. #6
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 549
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 549
    Points : 19 378
    Points
    19 378
    Par défaut
    on n'utilise pas ls ! :/
    ça pose des problème lors du parcours de sa sortie.
    en plus, ici, ça ne sert à rien.

    donc, -printf, c'est bien, mais as-tu compris ce que font %s et %s ? et en quoi crois-tu que cela va aider à la résolution de ton exercice.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 52
    Points : 44
    Points
    44
    Par défaut
    Ok c'est noté je vais essayé d'abandonner LS
    Mais Non pour l'instant pas assez cherché (printf sur MAN pas facile à comprendre) mais pas encore trouvé la signification de printf '%s ; %c ;'

    à part MAN ou trouver des info pertinentes à lire pour comprendre printf et ses options ?

    Merci
    à la semaine prochaine...

  8. #8
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 549
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 549
    Points : 19 378
    Points
    19 378
    Par défaut
    ah, mais ce n'est pas printf, c'est -printf, il s'agit de l'une des actions de find, il faut chercher, donc, dans le man find.

    mais comment, alors, as-tu choisi ce format (%s;%c;) ?

    PS: le man est intimidant, cependant les formats d'affichage sont clairement exposés.
    ce n'est guère plus qu'une liste - tu n'as qu'à faire des essais sur un seul fichier :
    Code par exemple : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ > monFichier
    $ find ./ -name monFichier -printf '%a\n'

    /!\ ne pas oublier le \n : -printf contrairement à echo n'ajoute pas de retour charriot.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  9. #9
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    salut,

    Citation Envoyé par philoeil Voir le message
    (...) dans l'ordre alphabétique des noms des fichiers (sans tenir compte des chemins des dossiers)
    ça va demander de ruser un peu, en particulier l'idée va être de trier d'abord et de faire le reste des traitements ensuite

    on peut par exemple demander à find -printf d'afficher les résultats sous la forme <nom fichier><séparateur><données souhaitées : inode, horodatage, chemin complet vers le fichier...>, puis trier avec sort, et se débarrasser de la première partie de la ligne jusqu'au séparateur avec un sed ou un cut.

    aussi une commande bien utile c'est tee, qui permet d'écrire chaque ligne dans un fichier et de l'afficher également sur la sortie standard (qu'on peut récupérer avec un pipe donc)

    le tout pourrait donner une commande du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find "$CHEMIN/" -iname "*.mm" -type f -printf "%f|%i;%Tx %TX;%p\n" | sort | cut -d'|' -f2- | tee fichier1 | sed 's#.*/##' > fichier2
    et le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $ cat fichier1
    156480;30/09/2019 17:52:30.7084270000;/rep1/rep2/Doublons/OrganisationRepertoiresIdeale22.mm
    156483;30/09/2019 17:52:33.7204270000;/rep1/rep2/Doublons/Doublons2/OrganisationRepertoiresIdeale23.mm
    156478;30/09/2019 17:52:28.6964270000;/rep1/rep2/Doublons/OrganisationRepertoiresIdeale.mm
    156479;30/09/2019 17:52:29.7044270000;/rep1/rep2/Doublons/Projet U2_4.mm
    156484;30/09/2019 17:52:34.7244270000;/rep1/rep2/Doublons/Doublons2/Projet U2.mm
    156482;30/09/2019 17:52:32.7164270000;/rep1/rep2/Doublons/Doublons2/Projet U2_V23.mm
    156481;30/09/2019 17:52:31.7124270000;/rep1/rep2/Doublons/Doublons2/Projet U2_V2.mm
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $ cat fichier2
    OrganisationRepertoiresIdeale22.mm
    OrganisationRepertoiresIdeale23.mm
    OrganisationRepertoiresIdeale.mm
    Projet U2_4.mm
    Projet U2.mm
    Projet U2_V23.mm
    Projet U2_V2.mm

  10. #10
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 549
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 549
    Points : 19 378
    Points
    19 378
    Par défaut
    ne pas oublier le \n : -printf contrairement à echo n'ajoute pas de retour charriot.
    par contre, quand on fait des traitements en chaîne, il faut mettre un caractère NULL (\0) pour que les noms de fichiers comportant un retour charriot soient correctement traités.
    sort et cut ont des options pour traiter ce caractère comme délimiteur.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  11. #11
    Membre éprouvé Avatar de balkany
    Homme Profil pro
    Touriste
    Inscrit en
    Juillet 2017
    Messages
    346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 346
    Points : 977
    Points
    977
    Par défaut
    Citation Envoyé par BufferBob Voir le message
    ça va demander de ruser un peu, en particulier l'idée va être de trier d'abord et de faire le reste des traitements ensuite
    Oui, en regardant un peu ça hier, j'en étais arrivé à la même conclusion du find | sort | cut.
    Du coup je m'étonnais que sort ne propose pas la possibilité de trier sur le dernier champ, avec une syntaxe du genre sort -t '/' -k -1. Ça manque ici.

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 52
    Points : 44
    Points
    44
    Par défaut
    Merci beaucoup à BufferBob, N_BaH, Balkany votre aide m’a été précieuse.

    Pour l’étape 1 et 2 c’est bon :
    code retenu
    J’ai choisi le caractère de séparation point virgule => ;
    entre mes 3 colonnes «nomdufichier» «infodateacces» et «chemin»
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find ~/Documents/EssaiRenomage/Doublons -iname "*.mm" -type f -printf "%f; dernier accès le %AA %Ad %AB %AY à %AH:%AM:%AS ;%h\n" | sort -k 1b,1 >RechDbl15.csv
    ce code me donne*bien les fichiers trier par ordre croissant de leurs noms et le détail de leurs dates d’accès et chemins:

    OrganisationRepertoiresIdeale22.mm; dernier accès le lundi 23 septembre 2019 à 18:33:06.0000000000 ;/home/phil/Documents/EssaiRenomage/Doublons
    OrganisationRepertoiresIdeale23.mm; dernier accès le lundi 23 septembre 2019 à 18:33:06.0000000000 ;/home/phil/Documents/EssaiRenomage/Doublons/Doublons2
    OrganisationRepertoiresIdeale.mm; dernier accès le lundi 23 septembre 2019 à 18:31:45.0000000000 ;/home/phil/Documents/EssaiRenomage/Doublons
    Projet U2_4.mm; dernier accès le lundi 23 septembre 2019 à 18:32:10.0000000000 ;/home/phil/Documents/EssaiRenomage/Doublons
    Projet U2.mm; dernier accès le dimanche 06 octobre 2019 à 09:07:07.0000000000 ;/home/phil/Documents/EssaiRenomage/Doublons/Doublons2
    Projet U2_V23.mm; dernier accès le lundi 23 septembre 2019 à 18:33:06.0000000000 ;/home/phil/Documents/EssaiRenomage/Doublons/Doublons2
    Projet U2_V2.mm; dernier accès le dimanche 06 octobre 2019 à 09:07:07.0000000000 ;/home/phil/Documents/EssaiRenomage/Doublons/Doublons2
    Pour l’étape 3
    Depuis RechDbl15.csv Je supprime les lignes 1 à 5 avec un editeur de texte et je garde que les 2 dernières pour faire une action TEST ici je souhaite renommer les 2 fichiers en OLD&NomDuFichier ce qui me crée un nouveau fichier Doublon16.csv

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    while IFS=';' read -r colonne1 colonne2 colonne3 ; do 
    ******echo "$colonne3" 
    anciennom=${colonne3}'/'${colonne1}***** 
    nouveaunom=${colonne3}'/'"OLD"${colonne1} 
    #echo "anciennom="${anciennom} 
    #echo "nouveaunom="${nouveaunom} 
    mv -iv "${anciennom}" "${nouveaunom}" 
    done < Doublon16.csv
    (J'ai rencontré une difficulté passagère avec des espaces en trop écrits dans une première version du code, mais c'est réglé)

    Il me reste à essayer pour de bon, je mettrai résolu la semaine prochaine si tout c'est bien passé.

    Quelques petites questions si vous voulez bien :
    N_Bah a écrit
    par contre, quand on fait des traitements en chaîne, il faut mettre un caractère NULL (\0) pour que les noms de fichiers comportant un retour charriot soient correctement traités.
    Je n'ai pas compris est-ce que j'ai une modification à prévoir dans mon code ?

    BufferBob a écit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find "$CHEMIN/" -iname "*.mm" -type f -printf "%f|%i;%Tx %TX;%p\n" | sort | cut -d'|' -f2- | tee fichier1 | sed 's#.*/##' > fichier2
    J'ai beaucoup appris en décryptant ton code
    Par contre je n'ai pas réussi à comprendre comment fonctionne le point ci apres "sed 's#.*/##' "
    le code suivant marche mais comment (J'ai découper en 3 étape pour ma meilleur compréhension)?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find ~/Documents/ShellEssais/Doublons -iname "*.mm" -type f -printf "%f|%i;%Tx %TX;%p\n" >Gros11.txt
    Resultat :
    Resultat
    OrganisationRepertoiresIdeale.mm|6685972;22/09/2019 16:34:45.5654811100;/home/phil/Documents/ShellEssais/Doublons/OrganisationRepertoiresIdeale.mm
    Projet U2_4.mm|6686001;26/02/2017 07:57:15.0000000000;/home/phil/Documents/ShellEssais/Doublons/Projet U2_4.mm
    OrganisationRepertoiresIdeale22.mm|6685958;22/09/2019 16:34:45.0000000000;/home/phil/Documents/ShellEssais/Doublons/OrganisationRepertoiresIdeale22.mm
    Projet U2_V2.mm|6686001;26/02/2017 07:57:15.0000000000;/home/phil/Documents/ShellEssais/Doublons/Doublons2/Projet U2_V2.mm
    Projet U2_V23.mm|6685960;26/02/2017 07:57:15.0000000000;/home/phil/Documents/ShellEssais/Doublons/Doublons2/Projet U2_V23.mm
    OrganisationRepertoiresIdeale23.mm|6685959;22/09/2019 16:34:45.0000000000;/home/phil/Documents/ShellEssais/Doublons/Doublons2/OrganisationRepertoiresIdeale23.mm
    Projet U2.mm|6686001;26/02/2017 07:57:15.0000000000;/home/phil/Documents/ShellEssais/Doublons/Doublons2/Projet U2.mm
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sort <Gros11.txt | cut -d'|' -f2- | tee fichier1 | sed 's#.*/##' > Grosfichier13.txt
    Resultat :
    6685958;22/09/2019 16:34:45.0000000000;/home/phil/Documents/ShellEssais/Doublons/OrganisationRepertoiresIdeale22.mm
    6685959;22/09/2019 16:34:45.0000000000;/home/phil/Documents/ShellEssais/Doublons/Doublons2/OrganisationRepertoiresIdeale23.mm
    6685972;22/09/2019 16:34:45.5654811100;/home/phil/Documents/ShellEssais/Doublons/OrganisationRepertoiresIdeale.mm
    6686001;26/02/2017 07:57:15.0000000000;/home/phil/Documents/ShellEssais/Doublons/Projet U2_4.mm
    6686001;26/02/2017 07:57:15.0000000000;/home/phil/Documents/ShellEssais/Doublons/Doublons2/Projet U2.mm
    6685960;26/02/2017 07:57:15.0000000000;/home/phil/Documents/ShellEssais/Doublons/Doublons2/Projet U2_V23.mm
    6686001;26/02/2017 07:57:15.0000000000;/home/phil/Documents/ShellEssais/Doublons/Doublons2/Projet U2_V2.mm
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sort <Gros11.txt | cut -d'|' -f2- | tee fichier1 | sed 's#.*/##' > Grosfichier13.txt
    Ca j'ai (je pense) compris
    sort <Gros11.txt = tri du fichier comme %f en debut de nom, les fichiers sont trier par ordre du champs "nomduFichier"
    | cut -d'|' -f2- =-d, --delimiter=DELIM utilisez le caractère DELIM au lieu d'un onglet pour le délimiteur de champ .=> ici c'est "|"
    | tee fichier1 =La commande tee est nommée d'après le séparateur en T dans la plomberie, qui sépare l'eau en deux directions et a la forme d'un T. majuscule.
    tee copie les données de l’entrée standard vers chaque FICHIER et vers la sortie standard. En effet, tee duplique son entrée, l’acheminant vers plusieurs sorties à la fois.

    LA ligne ci-après je n'ai pas compris comment ça marche
    | sed 's#.*/##' > Grosfichier13.txt =>PAs compris comment on obtient le résultat la substitution du slach désigné par # pas compris

    MERCI A TOUS

  13. #13
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 549
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 549
    Points : 19 378
    Points
    19 378
    Par défaut
    le problème apparaît quand le nom d'un fichier contient un \n.
    sort, par défaut, effectue ses tris sur des lignes en considérant que l'indication de fin de ligne est \n.

    par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ mkdir testDir
    $ cd testDir
    $ touch 'mon fichier' $'mon\nfichier'
    $ find -name 'mon*' | sort
    $ find -type f -name 'mon*' | sort | xargs -I {} echo '>{}<'
    >fichier<
    >./mon<
    >./mon fichier<
    $
    pour éviter cela, il faut faire terminer les lignes par un caractère NULL, et l'indiquer aux commandes auxquelles est passé le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $ find -type f -name 'mon*' -print0 | sort -z | xargs -0 -I {} echo ">{}<"
    >./mon
    fichier<
    >./mon fichier<
    $
    j'utilise xargs pour gérer l'affichage et mettre en évidence le comportement décrit.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  14. #14
    Expert éminent Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 035
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 035
    Points : 8 400
    Points
    8 400
    Par défaut
    Citation Envoyé par philoeil Voir le message
    je n'ai pas réussi à comprendre comment fonctionne le point ci apres "sed 's#.*/##' "
    c'est une substitution de regex classique s/// dans laquelle on cherche à matcher .*/, c'est à dire toute la ligne jusqu'au dernier / (et donc ne doit nous rester que le nom du fichier lui-même)
    du coup pour éviter d'avoir à échapper les caractères, ce qui donnerait un truc du style s/.*\///, on peut juste modifier le délimiteur de sed (# est un délimiteur valide)

  15. #15
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 277
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 277
    Points : 12 722
    Points
    12 722
    Par défaut
    En supposant que les noms de fichiers ne possède pas des '\n', alors on pourrait aussi faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find "$CHEMIN/" -iname '*.mm' -printf '%i;%Tx %TX;%h/\0%f\n' | sort -t '\0' -k2 -k1 | tr -d '\0'
    Cordialement.

  16. #16
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 52
    Points : 44
    Points
    44
    Par défaut
    Bonjour,
    Encore Merci à disedorgue, BufferBob et N_BaH pour votre aide et précisions

    J'en suis donc à mon étape 3 et je n'ai pas tout à fait le résultat attendu.
    Je m'explique :

    Mon objectif : Etape 3 executer par une commande shell des actions diverses (renomage, suppression, déplacement etc..) sur le fichier créé à l'étape 2 expurger par suppression des lignes (fichiers) que je ne veux pas toucher.

    Action de renomage en NomFichier_OLD

    Rappel de ce que j'ai fait :

    A l'étape 1 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    find ~ -iname "*.mm" -type f -printf "%f; dernier accès le %AA %Ad %AB %AY à %AH:%AM:%AS ;%h\n" | sort -k 1b,1 >~/Documents/RechDblmm.csv
    A l'étape 2 : Je supprime depuis un editeur de texte le ligne (fichiers) que je ne veux pas modifier, je sauvegarde le résultat de cette recherche et tri dans un fichier nommé ListmmRenomOLD.txt

    A l'etape 3.1 : Action de renomage en NomFichier_OLD

    Etap31Renom.sh :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #!/bin/bash
     
    while IFS=';' read -r colonne1 colonne2 colonne3 ; do
    #      echo "$colonne3"
    anciennom=${colonne3}'/'${colonne1}  
    nouveaunom=${colonne3}'/'${colonne1}"OLD"
    mv -v "${anciennom}" "${nouveaunom}" 1>FichierMsg 2>&1 2> >(sed 's/^/Erreur : /' >&2)
    done < ListmmEssRenomOLD.txt
    Ma difficulté rencontrée que je ne parviens pas encore à résoudre : Je pensais récupérer dans FichierMsg les messages des actions de renomage et des erreurs rencontrées mais je n'obtiens qu'une ligne
    Tous les fichiers de mon tests ont bien étaient renommés comme attendus.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    phil@phil-G750JH:~/Documents/EssaiRenomage$ ./Etap31Renom.sh 
    phil@phil-G750JH:~/Documents/EssaiRenomage$ cat FichierMsg 
    renamed '/home/phil/Documents/EssaiRenomage/Doublons/Doublons2/Projet U2.mm' -> '/home/phil/Documents/EssaiRenomage/Doublons/Doublons2/Projet U2.mmOLD'
    phil@phil-G750JH:~/Documents/EssaiRenomage$
    Où est mon erreur ?

    Merci à tous

  17. #17
    Membre éprouvé Avatar de balkany
    Homme Profil pro
    Touriste
    Inscrit en
    Juillet 2017
    Messages
    346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Touriste

    Informations forums :
    Inscription : Juillet 2017
    Messages : 346
    Points : 977
    Points
    977
    Par défaut
    Un petit > en plus, pour lui dire de continuer à écrire à la suite dans FichierMsg, au lieu de tout écraser à chaque ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mv -v "${anciennom}" "${nouveaunom}" 1>>FichierMsg 2>&1 2> >(sed 's/^/Erreur : /' >&2)
    +++

    Par ailleurs, tu peux te dispenser de rediriger la sortie d'erreur standard vers la sortie standard par 2>&1, puis la sortie standard vers la sortie d'erreur standard par >&2, en te contentant de laisser sed écrire depuis la sortie d'erreur standard vers la sortie standard (elle-même redirigée au préalable vers FichierMsg) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mv -v "${anciennom}" "${nouveaunom}" 1>>FichierMsg 2> >(sed 's/^/Erreur : /')

  18. #18
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 458
    Points
    13 458
    Par défaut
    Bonjour

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mv -v "${anciennom}" "${nouveaunom}" 1>FichierMsg 2>&1 2> >(sed 's/^/Erreur : /' >&2)
    Cette ligne est un peu torturée
    Soit tu rediriges le canal 2 comme le canal 1, soit tu le rediriges vers ta substitution de processus. (bravo d'ailleurs pour cette idée. Attention: fonctionne en bash, pas en sh)

    Est-ce qu'une commande comme celle-ci fonctionne mieux ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mv -v "${anciennom}" "${nouveaunom}" 1>FichierMsg 2> >(sed 's/^/Erreur : /' >FichierMsg)
    Une autre idée est de laisser filer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    while IFS=';' read -r colonne1 colonne2 colonne3 ; do
    #      echo "$colonne3"
        nom=${colonne3}'/'${colonne1}  
        mv -v "$nom" "$nom"OLD 2> >(sed 's/^/Erreur : /')
    done < ListmmEssRenomOLD.txt >FichierMsg
    Pas de problème d'écrasement, a priori.

    [grilled] posts croisés.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  19. #19
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 52
    Points : 44
    Points
    44
    Par défaut
    Merci Flodelarab

    [QUOTE=Flodelarab;11174143]

    Est-ce qu'une commande comme celle-ci fonctionne mieux ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mv -v "${anciennom}" "${nouveaunom}" 1>FichierMsg 2> >(sed 's/^/Erreur : /' >FichierMsg)
    Reponse : non Là il n'y a qu'une ligne, il manque le "1>>FichierMsg" je pense

    Une autre idée est de laisser filer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    while IFS=';' read -r colonne1 colonne2 colonne3 ; do
    #      echo "$colonne3"
        nom=${colonne3}'/'${colonne1}  
        mv -v "$nom" "$nom"OLD 2> >(sed 's/^/Erreur : /')
    done < ListmmEssRenomOLD.txt >FichierMsg

    reponse : oui là le résultat est identique

  20. #20
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 52
    Points : 44
    Points
    44
    Par défaut
    Merci Balkany ta suggestion était parfaite!

    Je clos ma discussion et je la place en résolu.

    Merci à tous

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 8
    Dernier message: 25/09/2008, 20h22
  2. Fichier BATCH pour exécuter une commande (Wake on LAN)
    Par snoopy69 dans le forum Windows XP
    Réponses: 0
    Dernier message: 23/04/2008, 07h14
  3. executer une commande shell en c++
    Par robux dans le forum Linux
    Réponses: 4
    Dernier message: 25/09/2007, 18h01
  4. [C] code pour executer une commande shell
    Par waldoun dans le forum Linux
    Réponses: 3
    Dernier message: 05/05/2007, 22h41
  5. execute une commande shell en java
    Par freakfm dans le forum API standards et tierces
    Réponses: 8
    Dernier message: 07/10/2006, 17h03

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