Hancurkan semua hardlink dalam folder

10

Saya memiliki folder yang berisi sejumlah file tertentu yang memiliki tautan keras (di folder yang sama atau di tempat lain), dan saya ingin menghapus tautan-tautan file-file ini, sehingga mereka menjadi independen, dan perubahan pada isinya tidak akan memengaruhi apa pun. file lain (jumlah tautannya menjadi 1).

Di bawah, saya memberikan solusi yang pada dasarnya menyalin setiap tautan keras ke lokasi lain, lalu memindahkannya kembali ke tempatnya.

Namun metode ini tampaknya agak kasar dan rawan kesalahan, jadi saya ingin tahu jika ada beberapa perintah yang akan menghapus hard-file untuk saya.

Jawaban kasar:

Temukan file yang memiliki tautan keras ( Edit : Untuk juga menemukan soket dll. Yang memiliki tautan keras , gunakan find -not -type d -links +1):

find      -type f -links +1 # files only
find -not -type d -links +1 # files, sockets etc.

Metode kasar untuk menghapus tautan file (menyalinnya ke lokasi lain, dan memindahkannya kembali): Edit: Seperti kata Celada, yang terbaik adalah melakukan cp -p di bawah ini, untuk menghindari kehilangan stempel waktu dan izin. Sunting: Buat direktori sementara dan salin ke file di bawahnya, alih-alih menimpa file temp, itu meminimalkan risiko untuk menimpa beberapa data, meskipun mvperintahnya masih berisiko (terima kasih @Tobu). Sunting: Cobalah untuk membuat direktori sementara di sistem file yang sama (@MikkoRantalainen).

# This is unhardlink.sh
set -e
for i in "$@"; do
  temp="$(mktemp -d -- "${i%/*}/hardlnk-XXXXXXXX")"
  [ -e "$temp" ] && cp -ip "$i" "$temp/tempcopy" && mv "$temp/tempcopy" "$i" && rmdir "$temp"
done

Jadi, untuk menghapus tautan semua tautan keras ( Edit : diubah -type fmenjadi -not -type d, lihat di atas):

find -not -type d -links +1 -print0 | xargs -0 unhardlink.sh
Suzanne Dupéron
sumber
Saya tidak akan menganggap itu 'kasar'. Satu-satunya cara untuk mendapatkan yang lebih cepat mungkin melakukan beberapa trik dengan system call sendfile () dan memutuskan tautan file sumber terbuka dan menulis ulang target di tempat. Terus terang itu tidak sepadan dengan usaha.
Matthew Ife
Dengan 'mentah', maksud saya, misalnya, ketika saya menjalankan perintah ini menggunakan cp -isakelar, itu meludahi saya beberapa pesan yang menanyakan apakah harus menimpa ./fileXXXXXX( $tempfile), meskipun tmpfile harus memberikan nama file yang unik, jadi harus ada menjadi semacam kondisi ras atau apa pun, dan dengan itu risiko kehilangan beberapa data.
Suzanne Dupéron
1
Itu normal bahwa file itu ada, Anda baru saja membuatnya dengan tempfile (nb: usang mendukung mktemp, tapi bukan itu yang menyebabkan masalah Anda).
Tobu
1
Anda unhardlink.shharus membuat direktori sementara di dalam direktori yang sama yang berisi file yang perlu dihapus tautannya. Kalau tidak, panggilan rekursif Anda dapat berulang di dalam sistem file lain dan Anda akhirnya memindahkan barang-barang di atas batas-batas filesystem karena direktori sementara Anda ada di direktori saat ini. Saya kira Anda bisa memberikan "$(dirname "$i")/hardlink-XXXXXX"argumen sebagai mktemp sebagai gantinya.
Mikko Rantalainen
1
@MikkoRantalainen Terima kasih banyak, diperbarui! Perhatikan bahwa jika filesystem itu adalah semacam unionfs atau fusefilesystem, itu mungkin sebenarnya dikirim path/to/hardlink-XXXke media penyimpanan fisik yang berbeda dari path/to/original-file, tetapi tidak ada banyak yang bisa dilakukan tentang itu.
Suzanne Dupéron

Jawaban:

9

Ada ruang untuk perbaikan dalam skrip Anda, misalnya menambahkan -popsi ke cpperintah sehingga izin dan stempel waktu akan dipertahankan di seluruh operasi pembatalan tautan, dan Anda bisa menambahkan beberapa penanganan kesalahan sehingga file temp dihapus jika terjadi kesalahan, tetapi ide dasar dari solusi Anda adalah satu-satunya yang akan berhasil. Untuk menghapus tautan file, Anda harus menyalinnya dan kemudian memindahkan salinannya kembali ke nama aslinya. Tidak ada solusi "kurang mentah", dan solusi ini memiliki kondisi balapan jika proses lain mengakses file pada saat yang sama.

Celada
sumber
Memang, saya selalu menggunakan cp -a saat menyalin hal-hal, untuk menjaga semuanya, kambuh dan salin symlink sebagai symlink. Tidak tahu mengapa saya lupa kali ini, tetapi setelah melihat jawaban Anda, saya mengerti saya telah mengacaukan semua stempel waktu saya, dan harus (agak menyakitkan) memulihkannya dari cadangan.
Suzanne Dupéron
5

Jika Anda ingin membakar ruang disk, dan Anda memiliki versi yang relatif modern tar(misalnya, apa yang ada di Ubuntu 10,04 dan CentOS 6), Anda dapat bermain dengan --hard-dereferenceopsi tersebut.

Sesuatu seperti:

$ cd /path/to/directory
$ ls -l *
bar:
total 12
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 1
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 3

foo:
total 12
-rw-rw-r-- 2 cjc cjc 3 May  6 19:07 1
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 4

(tempat saya berlari ln foo/[12] bar)

$ tar cvf /tmp/dereferencing.tar --hard-dereference .
$ tar xvf /tmp/dereferencing.tar
$ ls -l *
bar:
total 12
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 1
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 3

foo:
total 12
-rw-rw-r-- 1 cjc cjc 3 May  6 19:07 1
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 4

Dari halaman manual:

   --hard-dereference
          follow hard links; archive and dump the files they refer to
cjc
sumber
Saya menduga ada sedikit tar tidak bisa dilakukan. Perbaikan yang bagus.
Joseph Kern
Saya lupa menyebutkan bahwa saya tidak memiliki cukup ruang disk untuk menyalin semuanya. Pada dasarnya, metode Anda sama dengan cp -a --no-preserve=links /path/to/folder /path/to/copy && rm -rf /path/to/folder && mv /path/to/copy /path/to/folder, jika saya tidak salah. Saya kira metode Anda akan lebih efisien, karena tar akan melibatkan lebih sedikit pencarian disk, jadi kurang meronta-ronta. Seseorang dapat mencapai hal yang sama dengan rsync, dengan kinerja yang bahkan lebih rendah daripada metode cp :).
Suzanne Dupéron
1
Untuk menghindari menggunakan banyak disk tambahan, dimungkinkan untuk menjalankan sesuatu seperti tar cvf - --hard-dereference . | tar xf -tetapi mungkin ada kondisi balapan yang akan menyebabkan hal-hal meledak. Saya belum mencobanya, dan saya agak enggan melakukannya saat ini.
cjc