Convierta enlaces simbólicos a enlaces duros

25

Me gustaría convertir recursivamente enlaces blandos a enlaces duros en un directorio. He intentado algo como esto:

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

... pero tiene dos problemas principales:

  • no recursivo
  • recoge archivos que no son enlaces simbólicos

Sería bueno alimentar de alguna manera la línea anterior find -type l, pero no estoy seguro de cómo hacerlo.

Atila O.
fuente
1
Ver también [esta discusión] [1] ( cp -aH). [1]: unix.stackexchange.com/questions/94185/…
Michael Shigorin

Respuestas:

34

Este comando debería funcionar:

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

Cómo funciona:

  • find -type l encuentra todos los enlaces en el directorio actual.

  • -exec bash -c '...' {} \;invoca bash para ejecutar ....

    Pasa {}, el nombre del enlace que se está procesando actualmente, como un argumento, al que bash puede acceder como $0.

  • readlink -m "$0" devuelve la ruta absoluta del destino del enlace simbólico.

  • ln -f "$(readlink -m "$0")" "$0"sobrescribe ( -f) el enlace simbólico $0con un enlace duro a su objetivo.

Si el enlace no se puede convertir por algún motivo, permanecerá intacto e imprimirá un mensaje de error.

Dennis
fuente
Con respecto al último párrafo, ¿no sería suficiente especificar rutas absolutas hacia bashy ln?
Daniel Beck
2
Mi problema fue que readlink devuelve una ruta relativa por defecto, pero el -einterruptor lo soluciona.
Dennis
¿Cuál sería el comando para OSX?
Igor Markelov
@IgorMarkelov Lo siento, pero no tengo idea cuando se trata de OSX.
Dennis
1
En una Mac es: brew install coreutilsy find * -type l -exec bash -c 'ln -f "$(greadlink -m "$0")" "$0"' {} \;.
Igor Markelov