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 :

Recherche de chaines de caractères incomplètes


Sujet :

Shell et commandes GNU

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Candidat au Club
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Juillet 2014
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Responsable de service informatique

    Informations forums :
    Inscription : Juillet 2014
    Messages : 2
    Par défaut Recherche de chaines de caractères incomplètes
    Bonjour à tous.

    Suite à un crash d'un "vieux" disque dur (Sun OS), je suis dans l'obligation d'en regénérer un nouveau et d'y réinstaller divers fichiers.
    Une des archives que j'ai récupéré a été faite sous Windows, et elle a été très mal faite : les noms des fichiers ont été forcés en majuscule et tronqués à 8 caractères...

    Si l'écriture d'un script qui renomme les fichiers MAJUSCULES vers minuscules ne m'a posé de problème, je bloque sur la réalisation d'un script dont le besoin est le suivant :
    Tout un tas de fichiers restaurés portent de le nom "node_xxx.c (.h / .asm / ...)" (xxx est une chaine de caractères pseudo aléatoire qui remplace le nom d'origine). Ces fichiers contiennent tous le nom qu'ils portaient avant "l'archivage" à savoir NODE_<...>.c / .h / ...

    exemple : dans les fichiers source .c, c'est dans un commentaire type "/* Node NODE_0_E */" que l'on peut connaître le nom d'origine du fichier.

    Le script que je souhaite réaliser doit
    - Récupérer le nom complet NODE_<...> dans le fichier (NODE_0_E dans l'exemple ci dessus)
    - Renommer le fichier node_xxx en NODE_<...>

    J'ai commencé a faire le job à la mano mais le nombre de fichiers à traiter est "monstrueux". Un script serait vraiment très utile ...

    D'avance merci pour vos aides et indications.

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 840
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par JeanYves91 Voir le message
    exemple : dans les fichiers source .c, c'est dans un commentaire type "/* Node NODE_0_E */" que l'on peut connaître le nom d'origine du fichier.
    Bonjour
    Tu as pas mal expliqué ton problème mais pas tout à fait cependant. Par exemple dans un fichier ".asm" comment peut-on trouver le nom du fichier ?
    Et est-ce que ce nom est toujours précédé du mot clef "Node" ??? Cela aurait été bien d'avoir un exemple plus complet.

    Ceci dit, j'ai écrit ce script
    Code bash : 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
    #!/bin/sh
     
    # Traitement des fichiers passés en arguments
    for file in $*
    do
    	# Recherche de la chaine "Node"
    	info=$(fgrep "Node " $file)
     
    	# Contrôle de cohérence: vérification que la chaine existe et qu'elle est unique
    	# Si ce n'est pas le cas, je laisse tomber ce fichier
    	if test -z "$info" -o $(echo "$info" |wc -l) -gt 1
    	then
    		echo "$file non traité car incohérent"
    		continue
    	fi
     
    	# Récupération de l'extension du fichier à renommer
    	ext=$(echo "$file" |cut -f2- -d.)
     
    	# Récupération du dossier contenant le fichier à renommer
    	dir=$(dirname "$file")
     
    	# Extraction du nom du fichier (la chaine qui suit le mot "Node")
    	nom=$(echo "$info" |awk '{ for (i=1; i <= NF; i++) if ($i == "Node") { print $(i+1); break }}')
     
    	# On renomme
    	echo "$file => $dir/$nom.$ext"
    	mv "$file" "$dir/$nom.$ext"
    done

    Tu l'appelles en lui donnant à manger le ou les fichiers (par exemple node_xxx.c). Et si celui-ci (comme ton exemple) contient une chaine "Node toto" (avec la casse), alors il renomme "node_xxx.c" en "toto.c".
    Je ne suis pas certain qu'il convienne (t'as trop laissé d'inconnues dans l'exposé de ton problème) mais dans tous les cas ça te donnnera les bases pour faire le tien...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Candidat au Club
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Juillet 2014
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Responsable de service informatique

    Informations forums :
    Inscription : Juillet 2014
    Messages : 2
    Par défaut
    Bonjour

    Merci pour votre réponse, elle m'a bien aidé à progresser sur le script.

    J'ai omis de dire que j'utilise cygwin pour réaliser et exécuter ce script, ceci pouvant avoir de l'importance.

    Par rapport au script initial, j'ai apporté la recherche récursive et la "généricité" de l'appel. Du coup il y a eu des effets de bord sur la recherche de l'extension : le fichier était affiché comme ./r1/r2/r3/node_xxx.c et le cut ne fonctionnait pas.
    J'ai remplacé le cut par une commande sed.

    Ca marche nickel pour les fichiers .c et .h car j'ai la ligne dans chacun d'eux /* Node NODE_X_Y */

    voici votre script modifié par mes soins :

    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
     
     #!/bin/sh
     #Usage : renommer un fichier en récupérant une chaine contenue dans le fichier 
     # parametre 1 : filtre recherche fichier 
     # parametre 2 : Chaine recherchee 
     # parametre 3 : mot cle permettant de déterminer la chaine precedent le nom du fichier dans la ligne $info 
    #
    # Exemple :les fichiers node_xxx.c contiennent un commentaire /* Node NODE_A_B */
    # 
    # -> Renomme "node*.c" "/* Node" "Node"
    #
     for file in `find -type f -name "$1" -print;`
     do
         # Traitement des fichiers passés en arguments for file in $* 
         # Recherche de la chaine "Node"
         info=$(fgrep "$2" $file)
         echo "$info"
     
         # Contrôle de cohérence: vérification qu'il n'y a bien qu'une seul chaine
         # Si ce n'est pas le cas, je laisse tomber ce fichier
         if test $(echo "$info" |wc -l) -gt 1
         then
             echo "$file non traité car incohérent"
             continue
         fi
         # Récupération de l'extension du fichier à renommer
         # ext=$(echo "$file" |cut -f2- -d/)
         ext=$(echo "$file" |sed 's/.*\.//g')
     
         # Récupération du dossier contenant le fichier à renommer
         dir=$(dirname "$file")
     
         # Extraction du nom du fichier (la chaine qui suit le mot "$3")
         nom=$(echo "$info" |awk '{ for (i=1; i <= NF; i++) if ($i == "$3") { print $(i+1); break }}')
     
         # On renomme
         echo "$file => $dir/$nom.$ext"
         mv "$file" "$dir/$nom.$ext"
     
     done
    Par contre pour le fichier asm c'est plus ardu. On ne retrouve pas le nom du fichier sans extensions, et il est à plusieurs endroits.

    Typiquement, on va retrouver l'info dans une ligne de commande type
    .file "NODE_0_A.c"
    ou encore des commentaires en entête de fichier type
    ; cg30 -q -o -n -v40 -p -i -x -x -x -o NODE_0_A.if NODE_0_A.asm NODE_0_A.tmp

    Si j'arrive à récupérer un des NODE_0_A.xx, je pense que basename devrait me permettre d'avoir la chaine cherchée.

    Je continue à creuser l'analyse de la ligne. Si vous avez des idées / conseils pour réussir a extirper le NODE_0_A je suis preneur

    Cdt

  4. #4
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 293
    Par défaut
    Bonjour,

    ne considérant que la fin de ton dernier message, voilà comment je ferais avec sed:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $ cat nodenodenode.txt 
    Typiquement, on va retrouver l'info dans une ligne de commande type
    .file "NODE_0_A.c"
    ou encore des commentaires en entête de fichier type
    ; cg30 -q -o -n -v40 -p -i -x -x -x -o NODE_0_A.if NODE_0_A.asm NODE_0_A.tmp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ sed 's/\(.*"\(NODE[^.]*\.\)c".*\)\|\(.* \(NODE[^.]*\.\).* \4.* \4.*\)/\2\4/;tz;d;:z' nodenodenode.txt 
    NODE_0_A.
    NODE_0_A.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 664
    Par défaut
    Bonjour,

    for coupe les données qu'il parcours en mots, et non en lignes.
    si la sortie de la commande qu'il parcourt contient des espaces, le code ne fonctionnera pas.

    ce n'est peut-être pas le cas, ici, mais il est préférable d'appliquer les meilleures pratiques avant de prendre de mauvaises habitudes.
    utilise plutôt une boucle while, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ find ~ -maxdepth 1 -type f -iname "fichier*" -print0 |while read -r -d '' f; do echo ">$f<"; done
    >/home/nbah/fichier avec
    un alinea<
    >/home/nbah/fichier avec des espaces<
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 840
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par JeanYves91 Voir le message
    Bonjour
    Non, une fois suffit. Comme dans la vraie vie quoi. Tu dis bonjour quand tu entres dans la pièce mais pas à chaque phrase... si ???

    Citation Envoyé par JeanYves91 Voir le message
    le fichier était affiché comme ./r1/r2/r3/node_xxx.c et le cut ne fonctionnait pas.
    Ah merde oui ça c'est entièrement ma faute. Pour extraire l'extension je cutte sur le "." mais j'ai complètement zappé le cas où le chemin commence par "." !!!
    Et en plus, comble du comble, j'avais testé le dirname dans le cas où on n'a pas mis de chemin et il répond bien "." et ça même pas fait tilter...

    Mais bon, c'est facilement réparable. Suffit de supprimer le premier caractère si c'est "." quand on extrait l'extension, style
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	# Récupération de l'extension du fichier à renommer
    	ext=$(echo "$file" |sed -e "s/^\.//" |cut -f2- -d.)
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 293
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 293
    Par défaut
    Bonjour Sve@r, bonjour, bonjour,

    tu as raison, faut arrêter de souhaiter une bonne journée aux gens; elle risquerait d'arriver... la journée bonne.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    # Récupération de l'extension du fichier à renommer
    ext=$(echo "$file" |sed -e "s/^\.//" |cut -f2- -d.)
    Que c'est compliqué!
    Exemples:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ monfile="./r1/r2/r3/node_xxx.c"
    $ echo ${monfile##*.}
    c
    $ monfile="././r2/r3/node_xxx.c"
    $ echo ${monfile##*.}
    c
    $ monfile="r0/r1/r2/r3/node_xxx.c"
    $ echo ${monfile##*.}
    c
    $

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 840
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Flodelarab Voir le message
    tu as raison, faut arrêter de souhaiter une bonne journée aux gens; elle risquerait d'arriver... la journée bonne.
    Tu déformes mes propos (et c'est la seconde fois que je le remarque). Je ne dis pas qu'il ne peut pas souhaiter la bonne journée s'il en a envie, je dis juste qu'il ne doit pas s'y sentir obligé de le faire à chaque post...

    Citation Envoyé par Flodelarab Voir le message
    Que c'est compliqué!
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ a="./toto.tar.gz"
    $ echo "${a##*.}"
    gz
    $ echo "$a" |sed -e "s/^\.//" |cut -f2- -d\.
    tar.gz
    $

    Compliqué c'est vite dit. Ce ne sont pas des commandes vraiment très difficiles à comprendre ni utilisant des spécificités super complexes. Et en plus d'être 100% compatible Bourne Shell (après-tout, quand on présente une solution ce n'est peut-être pas mauvais d'essayer de couvrir le plus large public possible), au-moins ça fait ce que je veux, c'est à dire sortir l'extension complète.

    Toutefois c'est effectivement bien de montrer le cas "././r2/r3/node_xxx.c" qui reste bien évidemment toujours possible (et on peut enchainer sur "../autre_chemin")...
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ a="././r2/r3/toto.tar.gz"
    $ basename "$a" |cut -f2- -d\.
    tar.gz
    Bah oui, je sais, c'est encore trop compliqué pour toi...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

Discussions similaires

  1. rechercher une chaine de caractère dans un fichier
    Par 3FHFEB dans le forum Langage
    Réponses: 1
    Dernier message: 26/10/2006, 11h13
  2. Réponses: 9
    Dernier message: 07/09/2006, 13h47
  3. Recherche de chaine de caractères
    Par Surtep dans le forum MS SQL Server
    Réponses: 11
    Dernier message: 26/07/2006, 15h52
  4. recherche de chaine de caractéres
    Par donmamio dans le forum Langage
    Réponses: 6
    Dernier message: 04/05/2006, 07h22
  5. Chaine de caractères incomplète
    Par tonyC dans le forum ASP
    Réponses: 4
    Dernier message: 17/01/2006, 14h50

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