Menentukan apakah suatu file merupakan tautan keras atau tautan simbolik?

52

Saya membuat skrip shell yang akan mengambil nama file / path ke file dan menentukan apakah file tersebut merupakan tautan simbolik atau tautan keras.

Satu-satunya hal adalah, saya tidak tahu bagaimana cara melihat apakah itu tautan keras. Saya membuat 2 file, satu tautan keras dan satu tautan simbolik, untuk digunakan sebagai file uji. Tetapi bagaimana saya menentukan apakah suatu file merupakan tautan keras atau simbolis dalam skrip shell?

Juga, bagaimana saya menemukan partisi tujuan tautan simbolik? Jadi katakanlah saya memiliki file yang tertaut ke partisi yang berbeda, bagaimana saya menemukan jalur ke file asli itu?

k-Rocker
sumber
16
Apa yang Anda maksud dengan tautan keras? Semua file adalah tautan keras.
terdon
1
@terdon ln /foo/bar/ /foo/bar2membuat hardlink sambil ln -s /foo/bar /foo/bar2membuat symlink, itu yang dia maksud?
DisplayName
14
@DisplayName ya, tetapi semua file adalah tautan keras ke inode mereka. Begitulah cara kerja sistem file Linux. Dalam contoh Anda, bar2dan barkeduanya merupakan tautan keras, hanya menunjuk ke inode yang sama.
terdon
10
@DisplayName ya, itu adalah tautan keras ke inode lain . Tidak ada kontradiksi di sini. File adalah tautan ke inode. Itulah definisi suatu file. Dalam kasus Anda, Anda memiliki tautan ini di tempat yang berbeda tetapi itu tidak mengubah struktur data yang mendasarinya. Maksud saya adalah bahwa kedua bardan bar2sama-sama penting. Satu bukan tautan ke yang lain, keduanya merupakan tautan tetapi mengarah ke inode yang sama.
terdon
3
@ Hemat, saya katakan bahwa file biasa adalah hardlink dan hardlink yang dibuat lntidak berbeda dengan file biasa.
terdon

Jawaban:

42

Jawaban Jim menjelaskan bagaimana untuk menguji symlink: dengan menggunakan test's -Ltes.

Tetapi pengujian untuk "hard link" adalah, yah, sebenarnya bukan yang Anda inginkan. Hard link berfungsi karena cara Unix menangani file: setiap file diwakili oleh satu inode. Kemudian satu inode memiliki nol atau lebih nama atau entri direktori atau, secara teknis, tautan keras (apa yang Anda sebut "file").

Untungnya, statperintah, jika tersedia, dapat memberi tahu Anda berapa banyak nama yang dimiliki inode.

Jadi Anda mencari sesuatu seperti ini (di sini mengasumsikan implementasi GNU atau busybox stat):

if [ "$(stat -c %h -- "$file")" -gt 1 ]; then
    echo "File has more than one name."
fi

The -c '%h'bit mengatakan statuntuk hanya output jumlah hardlinks ke inode, yaitu, jumlah nama file memiliki. -gt 1kemudian periksa apakah itu lebih dari 1.

Perhatikan bahwa symlink, sama seperti file lainnya, juga dapat ditautkan ke beberapa direktori sehingga Anda dapat memiliki beberapa hardlink ke satu symlink.

derobert
sumber
ok, hanya untuk menjadi jelas, saya dapat menampilkan jumlah hardlink bahwa file telah menggunakan perintah stat dan jika lebih besar dari 1, maka ada file lain yang terhubung di suatu tempat di partisi.
k-Rocker
@ k-Rocker Ya. Kemudian ia memiliki nama kedua di suatu tempat di partisi.
derobert
1
Pada OS X atau * BSD, itu stat -f %l /path/to/file. Anda juga dapat menggunakan gstat -c %h /path/to/filejika GNU coreutils diinstal tanpa nama standarnya (dengan Homebrew pada OS X).
GDP2
29

Sebuah contoh:

$ touch f1
$ ln f1 f2
$ ln f1 f3
$ ln -s f1 s1
$ ln -s f2 s2
$ ln -s ./././f3 s3
$ ln -s s3 s4
$ ln s4 s5
$ ls -li
total 0
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f3
10802345 lrwxrwxrwx 1 stephane stephane 2 Nov 12 19:56 s1 -> f1
10802346 lrwxrwxrwx 1 stephane stephane 2 Nov 12 19:56 s2 -> f2
10802347 lrwxrwxrwx 1 stephane stephane 8 Nov 12 19:56 s3 -> ./././f3
10802384 lrwxrwxrwx 2 stephane stephane 2 Nov 12 19:56 s4 -> s3
10802384 lrwxrwxrwx 2 stephane stephane 2 Nov 12 19:56 s5 -> s3

The f1, f2dan f3direktori entri adalah file yang sama (inode yang sama: 10.802.124, Anda akan melihat jumlah link adalah 3). Itu adalah tautan keras ke file biasa yang sama .

s4dan s5juga file yang sama (10802384). Mereka adalah tipe symlink , tidak reguler . Mereka menunjuk jalan, di sini s3. Karena s4dan s5entri dari direktori yang sama, jalur relatif tersebut s3menunjuk ke file yang sama (yang dengan inod 10802347) untuk keduanya.

Jika Anda melakukan ls -Ll, itu meminta untuk mendapatkan informasi file setelah menyelesaikan symlink:

$ ls -lLi
total 0
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f3
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s3
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s4
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s5

Anda akan menemukan mereka semua menyelesaikan ke file yang sama (10802124).

Anda dapat memeriksa apakah suatu file bersinkronisasi dengan [ -L file ]. Demikian pula, Anda dapat menguji apakah suatu file adalah file biasa [ -f file ], tetapi dalam kasus itu, pemeriksaan dilakukan setelah menyelesaikan symlink.

hardlink bukan jenis file, mereka hanya nama yang berbeda untuk file (jenis apa pun).

Stéphane Chazelas
sumber
19

Menggunakan -hdan -Loperator testperintah:

-h file 
true if file is a symbolic link

-L file 
true if file is a symbolic link

http://www.mkssoftware.com/docs/man1/test.1.asp

Menurut utas SO ini , mereka memiliki perilaku yang sama, tetapi -Llebih disukai.

jimm-cl
sumber
ok keren, tapi bagaimana dengan tautan keras? saya memeriksa tapaknya, tetapi tidak ada tentang hard link. Jika -L mengembalikan false, apakah itu berarti hard link? atau hanya file biasa?
k-Rocker
1
Tautan keras berbagi hal yang sama inode. Juga, tautan lunak menunjukkan sebuah ldi awal ls -loutputnya ... Saya pikir Anda mungkin dapat menyatukan aturan-aturan itu dalam sebuah skrip, ditambah [[ -L file ]]tes untuk melihat apakah file yang diberikan lunak atau keras .
jimm-cl
ok, juga, bagaimana saya menemukan partisi tujuan tautan simbolik?
k-Rocker
3

Ada banyak jawaban yang benar di sini, tapi saya rasa tidak ada orang yang benar-benar mengatasi kesalahan persepsi. Pertanyaan aslinya pada dasarnya adalah "ketika saya membuat tautan simbolik, mudah untuk mengidentifikasinya setelah itu. Tapi saya tidak tahu bagaimana mengidentifikasi tautan keras." Dan ya, jawabannya pada dasarnya bermuara pada "Anda tidak bisa," dan kurang lebih menjelaskan mengapa, tetapi tampaknya tidak ada yang mengakui bahwa, memang, itu membingungkan dan aneh.

Jika Anda membaca semua ini dan Anda sudah tahu apa yang terjadi, maka Anda baik; Anda tidak perlu membaca sedikit pun. Jika Anda masih bingung, teruskan.

Jawaban yang benar-benar sangat singkat adalah bahwa tautan keras sama sekali bukan tautan sama sekali, tidak seperti tautan simbolis. Ini adalah entri baru dalam struktur direktori yang menunjuk ke sekelompok byte yang sama dengan entri direktori asli, dan setelah Anda membuatnya, itu sama 'nyata' dan sah seperti yang pertama. Setiap file 'normal' pada drive Anda memiliki setidaknya satu tautan keras; tanpa itu, Anda tidak akan melihatnya di mana pundirektori, dan tidak akan dapat merujuk atau menggunakannya. Jadi jika Anda memiliki file Fred.txt, dan Anda memasang tautan keras Wilma.txt dan Barney.txt ke sana, ketiga nama (dan entri direktori) merujuk ke file yang sama, dan mereka semua sama-sama valid. Tidak ada cara bagi OS untuk mengatakan bahwa salah satu entri dibuat ketika Anda menekan "save" di editor teks Anda, dan yang lain dibuat dengan perintah "ln".

OS memang harus melacak berapa banyak entri yang berbeda menunjuk ke file yang sama. Jika Anda menghapus Wilma.txt, tidak mengherankan bahwa Anda tidak membebaskan ruang apa pun di drive Anda. Tetapi jika Anda menghapus Fred.txt (file 'asli'), Anda masih tidak akan membebaskan ruang apa pun di drive Anda, karena data pada drive yang dikenal sebagai Fred.txt masih juga Barney.txt. Hanya ketika Anda menghapus semua entri direktori akan OS de-mengalokasikan ruang bahwa data itu sendiri menempati.

Jika Barney.txt telah menjadi tautan simbolis, maka menghapus Fred.txt akan menghilangkan alokasi ruang, dan Barney.txt sekarang akan menjadi tautan yang rusak. Juga, jika Anda memindahkan atau mengganti nama file yang memiliki tautan simbolik yang mengarah padanya, Anda akan memutus tautan tersebut. Tetapi Anda dapat memindahkan atau mengganti nama file yang ditautkan dengan keras semua yang Anda inginkan tanpa merusak entri direktori lain yang mengarah ke file / data itu, karena semuanya adalah entri direktori yang merujuk pada blok data yang sama pada drive (dengan menggunakan inode # dari data itu).

[Ini dua tahun kemudian, dan yang terakhir sedikit bingung saya selama satu menit, jadi saya pikir saya akan mengklarifikasi. Jika Anda mengetik "mv ./Wilma.txt ../elsewhere/Betty.txt" sepertinya Anda memindahkan file, tetapi pada kenyataannya, Anda tidak. Apa yang sebenarnya Anda lakukan adalah menghapus item baris dari daftar direktori dari direktori Anda saat ini, yang bertuliskan "nama 'Wilma.txt' dikaitkan dengan data yang dapat ditemukan dengan menggunakan inode ###### #, "dan menambahkan item baris baru ke daftar direktori direktori ../di suatu tempat yang mengatakan" nama 'Betty.txt' dikaitkan dengan data yang dapat ditemukan melalui inode ####### ". Inilah sebabnya mengapa Anda dapat 'memindahkan' file 2 gigabyte secepat file 2 kilobyte, selama Anda memindahkannya ke lokasi lain di drive yang sama.]

Karena OS harus melacak berapa banyak entri direktori yang berbeda menunjuk ke potongan data yang sama, Anda dapat mengetahui apakah file tertentu telah ditautkan dengan susah payah, walaupun Anda tidak dapat memastikan apakah entri direktori yang Anda pilih memiliki Sedang melihat adalah yang 'asli' atau tidak. Salah satu caranya adalah perintah "ls", khususnya "ls-l" (itu huruf kecil L setelah tanda hubung)

Untuk meminjam contoh sebelumnya ....

 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1

Huruf pertama adalah tanda hubung, jadi ini bukan direktori atau sesuatu yang eksotis, itu adalah file biasa 'biasa'. Tetapi jika itu benar-benar biasa, angka itu setelah bagian rwx-ish akan menjadi "1", seperti pada, "ada satu entri direktori yang menunjuk ke blok data ini." Tapi itu bagian dari demonstrasi tautan keras, jadi alih-alih tertulis "3".

Perhatikan bahwa ini mungkin dapat mengarah pada perilaku aneh dan misterius (jika Anda belum membungkus kepala dengan tautan keras, itu). Jika Anda membuka Fred.txt di editor teks Anda dan membuat beberapa perubahan, apakah Anda akan melihat perubahan yang sama di Wilma.txt dan Barney.txt? Mungkin. Mungkin. Jika editor teks Anda menyimpan perubahan dengan membuka file asli dan menulis perubahan itu, maka ya, ketiga nama masih akan menunjuk pada teks yang sama (baru diubah). Tetapi jika editor teks Anda membuat file baru (Fred-new-temp.txt), tulis versi Anda yang diubah itu, lalu hapus Fred.txt, lalu ganti nama Fred-new-temp.txt menjadi Fred.txt, Wilma dan Barney akan masih menunjuk ke versi asli, bukan versi yang baru diubah. Jika Anda tidak mengerti tautan keras, ini bisa membuat Anda sedikit marah. :) [Oke, sebenarnya saya tidak tahu secara pribadieditor teks yang akan melakukan hal yang baru-file / rename, tapi saya tahu banyak program lain yang melakukan hal itu, jadi tetap waspada.]

Catatan terakhir: salah satu hal yang diperiksa oleh 'fsck' (sistem file) adalah jika ada blok data pada drive Anda yang entah bagaimana tidak lagi dirujuk oleh entri direktori. Terkadang ada yang tidak beres, dan satu-satunya entri direktori yang menunjuk ke inode akan dihapus tetapi ruang drive itu sendiri tidak ditandai sebagai "tersedia." Jadi salah satu tugas fsck adalah mencocokkan semua ruang yang dialokasikan dengan semua entri direktori untuk memastikan bahwa tidak ada file yang tidak direferensikan. Jika menemukan beberapa, itu menciptakan entri direktori baru dan menempatkannya di "hilang + ditemukan".

Snarke
sumber
Hanya ingin tahu, apa itu "program lain yang melakukan hal itu"?
phk
@ phk Tidak tahu apa yang dia pikirkan secara spesifik, tapi itu adalah pendekatan yang cukup umum untuk melakukan tindakan yang bisa memakan waktu lama dan akan membuat Anda dalam keadaan tidak pasti jika gagal. Misalnya, jika Anda mencoba mengunduh dari server jarak jauh, dan Anda tahu ada kemungkinan server bisa habis, maka salah satu pendekatannya adalah mengunduh seluruh konten ke file temp. Dengan begitu jika ada yang salah dengan unduhan Anda masih memiliki file aslinya.
cwallenpoole
Satu-satunya program yang saya tahu pasti adalah FreeHand, karena jika / ketika crash saat save, ada file sementara yang tertinggal, daripada file asli yang rusak. Tetapi saya telah melihat program lain melakukannya juga; Saya tidak bisa memberikan contoh spesifik kepada Anda saat ini.
Snarke
2

Anda dapat menggunakan readlink FILE; echo $?. Ini mengembalikan 1 saat hardlink dan 0 saat symlink.

Dari halaman manual: "Ketika dipanggil sebagai readlink, hanya target dari tautan simbolik yang dicetak. Jika argumen yang diberikan bukan tautan simbolik, readlink tidak akan mencetak apa pun dan keluar dengan kesalahan."

pengguna2103720
sumber