Convertir des liens symboliques en liens physiques

25

Je voudrais convertir de manière récursive des liens logiciels en liens physiques dans un répertoire. J'ai essayé quelque chose comme ça:

for f in *; do (mv $f{,~} && ln $(readlink $f~) && rm $f~) done

… Mais il a deux problèmes majeurs:

  • pas récursif
  • récupère les fichiers qui ne sont pas des liens symboliques

Ce serait bien de fournir la ligne ci-dessus find -type l, mais je ne sais pas comment faire.

Attila O.
la source
1
Voir aussi [cette discussion] [1] ( cp -aH). [1]: unix.stackexchange.com/questions/94185/…
Michael Shigorin

Réponses:

34

Cette commande devrait fonctionner:

find -type l -exec bash -c 'ln -f "$(readlink -m "$0")" "$0"' {} \;

Comment ça fonctionne:

  • find -type l trouve tous les liens dans le répertoire courant.

  • -exec bash -c '...' {} \;invoque bash pour s'exécuter ....

    Il passe {}- le nom du lien en cours de traitement - comme argument, auquel bash peut accéder en tant que $0.

  • readlink -m "$0" renvoie le chemin absolu de la destination du lien symbolique.

  • ln -f "$(readlink -m "$0")" "$0"écrase ( -f) le lien symbolique $0avec un lien dur vers sa cible.

Si le lien ne peut pas être converti pour une raison quelconque, il restera intact et ln affichera un message d'erreur.

Dennis
la source
Concernant ce dernier paragraphe, ne suffirait-il pas de spécifier des chemins absolus vers bashet ln?
Daniel Beck
2
Mon problème était que readlink renvoie un chemin relatif par défaut, mais le -ecommutateur corrige cela.
Dennis
Quelle serait la commande pour OSX?
Igor Markelov
@IgorMarkelov Je suis désolé, mais je n'ai aucune idée en ce qui concerne OSX.
Dennis
1
Sur un Mac c'est: brew install coreutilset find * -type l -exec bash -c 'ln -f "$(greadlink -m "$0")" "$0"' {} \;.
Igor Markelov