Konversikan symlink ke tautan keras

25

Saya ingin mengonversi tautan lunak menjadi tautan keras di direktori secara rekursif. Saya sudah mencoba sesuatu seperti ini:

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

... tetapi memiliki dua masalah utama:

  • tidak rekursif
  • mengambil file yang bukan tautan simbolis

Akan lebih baik untuk memberi makan entah bagaimana baris di atas find -type l, tapi saya tidak yakin bagaimana melakukannya.

Attila O.
sumber
1
Lihat juga [diskusi ini] [1] ( cp -aH). [1]: unix.stackexchange.com/questions/94185/…
Michael Shigorin

Jawaban:

34

Perintah ini harus bekerja:

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

Bagaimana itu bekerja:

  • find -type l menemukan semua tautan di direktori saat ini.

  • -exec bash -c '...' {} \;memanggil bash untuk dieksekusi ....

    Itu lewat {}- nama tautan yang saat ini sedang diproses - sebagai argumen, yang dapat diakses oleh bash $0.

  • readlink -m "$0" mengembalikan jalur absolut dari tujuan tautan simbolik.

  • ln -f "$(readlink -m "$0")" "$0"menimpa ( -f) tautan simbolik $0dengan tautan keras ke targetnya.

Jika tautan tidak dapat dikonversi karena alasan tertentu, tautan itu akan tetap tidak tersentuh dan ln akan mencetak pesan kesalahan.

Dennis
sumber
Mengenai paragraf terakhir itu, tidakkah cukup untuk menentukan jalur absolut ke bashdan ln?
Daniel Beck
2
Masalah saya adalah bahwa readlink mengembalikan jalur relatif secara default, tetapi -esaklar memperbaikinya.
Dennis
Apa yang akan menjadi perintah untuk OSX?
Igor Markelov
@IgorMarkelov Maaf, tapi saya tidak punya petunjuk tentang OSX.
Dennis
1
Di Mac, itu adalah: brew install coreutilsdan find * -type l -exec bash -c 'ln -f "$(greadlink -m "$0")" "$0"' {} \;.
Igor Markelov