Memutus tautan keras di tempat?

13

Saya menjaga dotfile saya di bawah kontrol versi dan skrip yang menyebarkannya membuat tautan keras. Saya juga menggunakan etckeeperuntuk menempatkan /etckontrol versi di bawah saya . Baru-baru ini saya mendapat peringatan seperti ini:

warning: hard-linked files could cause problems with bzr

Salinan sederhana ( cp filename.ext filename.ext) tidak akan berfungsi:

cp: `filename.ext' and `filename.ext' are the same file

Mengganti nama / memindahkan file - kecuali di seluruh volume - juga tidak merusak hard-link.

Jadi pertanyaan saya adalah: adakah cara untuk memutus tautan-keras ke suatu file tanpa benar-benar harus tahu di mana tautan-tautan lainnya ke file tersebut?

0xC0000022L
sumber
2
Perintah "rm" memecah tautan keras.
Johan

Jawaban:

14
cp -p filename filename.tmp
mv -f filename.tmp filename

Menjadikannya skrip:

dir=$(dirname -- "$filename")
tmp=$(TMPDIR=$dir mktemp)
cp -p -- "$filename" "$tmp"
mv -f -- "$tmp" "$filename"

Melakukan salinan terlebih dahulu, kemudian memindahkannya ke tempatnya, memiliki keuntungan bahwa file secara atom berubah dari menjadi tautan keras menjadi salinan terpisah (tidak ada titik waktu di mana filenamesebagian atau hilang).

Gilles 'SANGAT berhenti menjadi jahat'
sumber
7

Anda mungkin bermaksud memisahkan hard-link menjadi file yang terpisah dan independen.

mv hardlink tempname && cp tempname hardlink && rm tempname

Hardlink adalah koneksi antara entri dalam direktori dan blok inode pada disk.

inodes menyimpan meta-data file, dan untuk file kecil, beberapa sistem file menyimpan data dalam inode, jika tidak pointer ke blok data, dan untuk file yang sangat besar, tidak langsung dan daftar pointer ganda tidak langsung ke unit alokasi disk.

Apapun, koneksi antara nama file (Yang menghasilkan perintah ls) dan blok inode yang menyimpan meta-data ini, disebut hard link.

Memiliki banyak tautan keras ke satu file berarti inode yang sama dirujuk oleh lebih dari satu entri direktori, mungkin di direktori yang berbeda (pada sistem file tunggal)

rm menghapus entri nama file dari direktori. Setelah inode tidak lagi dirujuk oleh file apa pun, ruangnya dibebaskan untuk digunakan oleh file lain.

Johan
sumber
Memang. Inilah yang cpdan mvcontoh - contoh tersirat. Jadi tidak ada jalan lain menggunakan file sementara, saya mengerti.
0xC0000022L
@ 0xC0000022L, Tidak, inode tidak mengandung pointer ke inode lainnya. Hanya untuk blok data (atau mereka dapat berfungsi ganda sebagai ruang data jika objek kecil).
vonbrand
4
Pastikan izin dan data lainnya dipertahankan saat menyalin, yaitu .e. gunakan cp -a(setidaknya GNU coreutils).
vonbrand
@ 0xC0000022L, jika Anda perhatikan dengan teliti, hanya ada nama sementara untuk file asli, file baru dibuat hanya pada langkah terakhir.
vonbrand
@vonbrand Mereka memang bisa, tergantung pada sistem file apa yang digunakan.
Johan
4

Letakkan ini di akhir file ~ / .bashrc Anda.

delink () { tmpfile="$1$(date)"; cp -a "$1" "$tmpfile"; mv "$tmpfile" "$1"; }

Jalankan seperti ini

delink filename
Rucent88
sumber
3

Cara terbaik untuk melakukannya dengan skrip bash adalah seperti ini:

if [ -f "$1" ] ; then
dir="$(dirname -- "$1")"
tmpfile="$(mktemp --tmpdir="$dir")"
cp --preserve=all -f -- "$1" "$tmpfile"
mv -f -- "$tmpfile" "$1"
fi

poin yang perlu diperhatikan:

  • periksa apakah file tersebut adalah file biasa sebelum mencoba menyalinnya
  • simpan file lama di tempatnya sampai salinan siap
  • gunakan mktempuntuk menghasilkan file yang dijamin tidak ada
  • gunakan -funtuk memaksa menimpa dan --preserve=alluntuk menjaga metadata semirip mungkin dengan file asli
  • menggunakan --dan "mengutip jalur yang berisi spasi dan / atau dimulai dengan-

Melakukan penggantian tanpa membuat file sementara tidak dimungkinkan dengan panggilan sistem linux saat ini (3.16): sementara dimungkinkan untuk menimpa file secara atom (yaitu, menghapus file lama dan ganti dengan yang baru sebagai operasi tunggal), itu tidak mungkin untuk melakukannya dengan file yang tidak memiliki nama pada sistem file (yaitu file sementara yang dibuat menggunakan O_TMPFILEflag of openfunction) karena renamefungsi tersebut memerlukan nama file sebagai input (tidak ada versi renameyang mengambil sebagai input deskriptor file - lihat di sini untuk detail)

pqnet
sumber
1
Perhatikan bahwa Anda gagal mengutip nama dalam panggilan Anda dirnamedan mktemp. Memperbaiki itu untuk Anda ...
derobert
@derobert oh terima kasih, tetapi ini tidak akan berhasil karena ada tanda kutip ganda bersarang ... perlu diperbaiki lagi! Agak membenci bash
pqnet
3
Ini akan bekerja karena $( ... )substitusi -style perintah. Salah satu alasannya lebih bagus daripada ` ... `gaya.
derobert
@derobert bagus, tidak tahu itu. Juga, bagaimana Anda bisa menggunakan tag kode `inline?
pqnet
Anda dapat melarikan diri dari mereka dengan garis miring terbalik. Jadi untuk membuat `Anda dimasukkan: `\``(tentu saja, saya lolos dua kali untuk membuatnya menunjukkan kepada Anda apa yang Anda ketik).
derobert
-1

Perintah yang Anda cari adalah unlink

Jenny D
sumber
Mungkin pertanyaan saya tidak jelas, tetapi oleh "di tempat" dan contoh-contoh dengan cpdan mvsaya bermaksud menjelaskan bahwa saya ingin file itu ada sesudahnya.
0xC0000022L
Ah, saya tidak menemukan yang jelas, tidak. Anda harus pergi dengan jawaban Johan, kalau begitu.
Jenny D
1
Perintah "unlink" hanya menghapus file (apa yang dilakukan unlink () system call).
Raúl Salinas-Monteagudo
-1

Jika Anda mencari semua nama file yang merupakan tautan ke file ini maka Anda dapat menggunakan:

find -samefile myknowhardlinkfile

juga ls -il myknowhardlinkfileakan menunjukkan jumlah nama file yang di-link ke inode yang sama (bidang ketiga).

101612442 -rw-rw-r--. 2 me me 0 Aug  5 07:07 myknowhardlinkfile
Jean-Pierre Laurin
sumber
Ini sebenarnya tidak menjawab pertanyaan, meskipun itu bisa berguna.
Flimm