J'ai un gros paquet de liens symboliques dont la destination a changé. Je souhaite modifier ces liens pour qu'ils pointent vers le bon endroit.
Facile !
Hé ben non, je n'y arrive pas :)
Seul un élément du chemin est à modifier :
Les liens sont dans /home/kerro/xxxxxx/ (mélangés à d'autres fichiers)
ancien = /media/yyyy/zzzz/fichier_cible
nouveau = /mnt/yyyy/zzzz/fichier_cible
Il me faut donc faire 'ln -s /mnt/yyyy/zzzzz/fichier_cible /home/kerro/xxxxxx/lien1'
Je tente avec :
find /home/kerro/xxxxx -type l -print0 | xargs -0 -n 1 -I {} ln -s $(readlink -m {} \| sed 's/$.media/mnt/') {}
mais cela échoue lamentablement.
En simplifiant la commande, je bute sur :
echo '/toto' | xargs -0 -n 1 -I {} echo $(readlink -m '{}')
--> /home/kerro//toto alors que /toto est attendu
Je dois avoir les yeux plein de merde, je ne pige pas le problème.
# Ordre d'évaluation
Posté par Barnabé . Évalué à 3. Dernière modification le 25 septembre 2012 à 03:04.
readlink -m '{}' est évalué en premier, sans substitution, cela donne /home/kerro/{} .
Puis {} est remplacé par /toto, cela donne /home/kerro//toto
Question, pourquoi se compliquer la vie avec le -print0 de find et le xargs compliqué ?
J'essaierais un truc comme ça :
avec change_link un programme annexe ou une fonction
ln -s $(readlink -m "$1" \| sed 's/$.media/mnt/') "$1"
[^] # Re: Ordre d'évaluation
Posté par Kerro . Évalué à 2.
Je ne pige pas pourquoi readlink -m '{}' est évalué en premier sans substitution, puisque le principe de xargs est, justement, de faire ça en boucle.
Concernant l'utilisation d'une fonction, c'était le plan B. Mais je tenais à trouver la solution en une ligne :)
[^] # Re: Ordre d'évaluation
Posté par gaaaaaAab . Évalué à 2.
absolument pas, et même au contraire !
xargs fabrique une ligne séparée par des espaces à partir d'une liste séparée par des retours chariot et invoque la commande en paramètre avec cette liste. Autrement dit:
revient au final à
le problème pour ton ln, c'est qu'on voudrait plutôt que ça devienne
vu que le répertoire cible pour les liens doit être le dernier argument de ln.
A ma connaissance, xargs ne permet pas de préciser à quel endroit de la commande on veut que la liste séparée par des espaces soit injectée (mais j'aimerais bien que quelqu'un me contredise et me montre comment faire !).
[^] # Re: Ordre d'évaluation
Posté par Kerro . Évalué à 2.
C'est l'option
-I replace-str
Ou encore :
Dans cet exemple on voit bien que
echo '***{}***'
est évalué à chaque fois.Donc je ne pige pas pourquoi mon readlink ne fonctionne pas. Il y a un effet de bord qui vient d'ailleurs et que je ne saisi pas.
[^] # Re: Ordre d'évaluation
Posté par Barnabé . Évalué à 2.
Prenons ton deuxième exemple :
Ce qui se passe est que lorsque ton shell évalue la ligne de commande, il va évaluer $(readlink -m '{}') avant de passer le résultat de cette évaluation à xargs.
L'évaluation de $(readlink -m '{}') donne, dans ton cas, /home/kerro/{}
Donc tout se passe comme si tu avais écrit :
Ce qui donne bien le résultat que tu obtiens.
[^] # Re: Ordre d'évaluation
Posté par Kerro . Évalué à 2.
C'est tellement évident…
La honte :)
Merci de m'avoir éclairé.
[^] # Re: Ordre d'évaluation
Posté par gaaaaaAab . Évalué à 3. Dernière modification le 26 septembre 2012 à 00:25.
ah chouette ! merci pour la réponse, j'ai appris un truc !
du coup, en prenant en compte le commentaire de Barnabé sur l'évaluation du readlink, il "suffit" de faire ce qu'il faut pour readlink soit évalué à chaque itération au lieu d'être interpréter sur la ligne de commande.
Du coup, on peut aussi s'en tirer avec:
# Faire un while ?
Posté par M.Poil (site web personnel) . Évalué à 2.
Tout simplement ?
Is it a Bird? Is it a Plane?? No, it's Super Poil !!!
[^] # Re: Faire un while ?
Posté par Kerro . Évalué à 3.
Je tentais avec xargs sans avoir pensé à une autre solution. De la merde dans les yeux je disais.
Voici la version qui fonctionne :
[^] # Re: Faire un while ?
Posté par BAud (site web personnel) . Évalué à 3.
Tu peux éditer l'entrée de forum pour indiquer
[résolu]
:-)bizarre ton
j'utilise plutôt la syntaxe
Cela permet de gérer les manipulations de répertoire (où un
/
traîne souvent), sans avoir à échapper le caractère/
vu que j'utilise#
comme séparateur des chaînes ;-) Bon, j'ai sans doute été traumatisé par les exécutions de programmes shell dans des programmes shells en ksh où les caractères d'échappement sautaient (et il fallait les échapper une, deux ou plus de fois… pour qu'ils soient pris en compte), mais pas toujours de la même façon, sinon c'est pas drôle… (selon le nombre d'appels iirc).# zsh
Posté par 태 (site web personnel) . Évalué à 3. Dernière modification le 25 septembre 2012 à 09:16.
Je ne sais pas utiliser find, donc j'utiliserais un peu de zsh dans une boucle for :
Explication : le @ permet de ne trouver que les liens symboliques, le
:A
résout le chemin absolu de la destination.# FHS
Posté par 🚲 Tanguy Ortolo (site web personnel) . Évalué à 1.
Curieux ton exemple. Tu es passé d'un chemin standard
/media/truc
vers un chemin non-standard/mnt/truc
. Sachant que, d'après la FHS,/mnt
est fait pour les montages temporaires, je te conseillerais plutôt de revenir à ta convention précédente.[^] # Re: FHS
Posté par NeoX . Évalué à 6.
bizarre j'aurais cru l'inverse :
- les montages temporaires dans /media (clef USB, CDROM)
- les montages permanents dans /mnt
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.