Bagaimana cara mendapatkan path lengkap file asli dari tautan simbolik lunak?

99

Saya ingin scpfile ke server. File tersebut adalah tautan simbolis, dan sebenarnya yang ingin saya lakukan adalah menyalin file sumber. Lagi pula saya tidak ingin melacak jalur file sumber secara manual, karena itu bisa diganti. Jika saya bisa mendapatkan path absolut file sumber, saya bisa sepdengan itu. Bagaimana saya bisa mendapatkan jalan?

Eonil
sumber
2
Sebagian besar scpversi mengikuti symlink secara default, bukan? Anda harus memeriksa milik Anda dan mungkin menyelamatkan diri dari pekerjaan.
jw013
@ jw103 Terima kasih telah memberi tahu saya. Saya tidak tahu. :)
Eonil
2
Catatan: scp -rmemaksa mengikuti symlink.
Eonil

Jawaban:

129

Coba baris ini:

readlink -f `which command`

Jika commandada di $PATHvariabel Anda , jika tidak, Anda harus menentukan jalur yang Anda tahu.

bunga aster
sumber
12
-fakan mengembalikan jalur ke target akhir yang tidak ada, asalkan target tautan menengah ada ... Gunakan -euntuk menghindari ini, yaitu. -eakan mengembalikan nol jika target akhir tidak ada.
Peter.O
10
-fsalah dengan readlink: illegal option -- fdi OSX. Menghapusnya berfungsi dengan baik.
Heath Borders
2
@HeathBorders Untuk OSX jika Anda telah menginstal homebrew coreutils, Anda juga dapat menggunakannya greadlink.
Adam Gent
23

Di Linux, readlinkbaca konten symlink, dan readlink -fikuti symlinks ke symlinks ke symlinks, dll., Sampai ia menemukan sesuatu yang bukan symlink.

Ini tidak diperlukan untuk scp: scp selalu mengikuti symlink (selalu menyalin konten file, mengabaikan metadata kecuali yang -pmempertahankan waktu dan mode file bila memungkinkan).

Jika Anda merasa kecewa dengan metadata scp yang bisa dan tidak bisa dipertahankan, saya sarankan menggunakan rsync. Tanpa opsi, rsync menyalin konten file mengabaikan metadata. Opsi yang biasa digunakan -amempertahankan semua metadata varietas kebun (waktu, tautan simbolik, izin, dan kepemilikan), dan ada opsi untuk melestarikan metadata eksotis seperti ACL dan tautan keras.

Gilles
sumber
readlink hanya melakukan satu langkah untuk membaca tautan. misalnya di ubuntu kita memiliki / bin / zsh, yang disinkronkan ke / etc / alternative / zsh, tetapi ini adalah symlink kedua. Akhirnya kita tidak akan mendapatkan jalur file atau direktori nyata. Hal yang sama dengan perintah stat. Hanya readlink dengan opsi -f yang menyelesaikan semua.
Znik
9

Saya menggunakan perintah ls, stat, readlink.

Ambil file /etc/localtimesebagai contoh

[flying@lempstacker ~]$ ls /etc/localtime 
/etc/localtime
[flying@lempstacker ~]$ ls -l /etc/localtime
lrwxrwxrwx. 1 root root 35 Aug  2 22:41 /etc/localtime -> ../usr/share/zoneinfo/Asia/Shanghai

Operasi

Menggunakan stat

[flying@lempstacker ~]$ stat /etc/localtime
  File: ‘/etc/localtime’ -> ‘../usr/share/zoneinfo/Asia/Shanghai’
  Size: 35          Blocks: 0          IO Block: 4096   symbolic link
Device: fd01h/64769d    Inode: 272202388   Links: 1
Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2016-11-23 09:00:59.999887800 +0800
Modify: 2016-08-02 22:41:26.090389904 +0800
Change: 2016-08-02 22:41:26.090389904 +0800
 Birth: -
[flying@lempstacker ~]$ stat -c "%N" /etc/localtime
‘/etc/localtime’ -> ‘../usr/share/zoneinfo/Asia/Shanghai’

Menggunakan readlink

[flying@lempstacker ~]$ readlink /etc/localtime
../usr/share/zoneinfo/Asia/Shanghai
[flying@lempstacker ~]$ readlink -f /etc/localtime
/usr/share/zoneinfo/Asia/Shanghai

Sepertinya perintah readlink -fitu lebih baik.

Penjelasan

-f, --canonicalize: canonicalize dengan mengikuti setiap symlink di setiap komponen nama yang diberikan secara rekursif; semua kecuali komponen terakhir harus ada —— Dariman readlink

Gorgon
sumber
6

Stat akan memberi Anda informasi ini:

$ stat current
  File: `current' -> `/home/user/releases/build/'
  ...
jumlahnya banyak
sumber
readlink hanya melakukan satu langkah untuk membaca tautan. misalnya di ubuntu kita memiliki / bin / zsh, yang disinkronkan ke / etc / alternative / zsh, tetapi ini adalah symlink kedua. Akhirnya kita tidak akan mendapatkan jalur file atau direktori nyata. Hal yang sama dengan perintah stat. Hanya readlink dengan opsi -f yang menyelesaikan semua.
Znik
5

Anda bisa melakukannya

readlink -f `which command`

atau Anda bisa mendapatkan yang serupa di Linux

stat `which command` | grep File

Jika Anda menambahkan ini ke skrip, periksa kesalahannya. Jika Anda tidak ingin melihat pesan kesalahan dalam kasus ketika tautan sym tidak ada, lanjutkan dengan sesuatu seperti

readlink -f "`which command`" 
Alexandre Santos
sumber
stat dan realink tanpa -f hanya melakukan satu langkah. maka lebih baik panggil readlink -f.
Znik
3

Saya akan menggunakan realpath <symlink>.

Mungkin yang Anda sebut 'sumber' adalah file 'target' sesuai dengan penggunaan ln:Usage: ln [OPTION]... [-T] TARGET LINK_NAME

XavierStuvw
sumber
Terima kasih Ini bekerja seperti pesona! dengan Mac OSX! di mana readlinktidak memotongnya ... mac bodoh. lol
JayRizzo
0

readlink -f 'which java' tidak bekerja untuk saya.

Tapi ini berhasil:

readlink -f $(which java)
NonCreature0714
sumber
3
Tidak berhasil karena `tidak '.. tetapi $()lebih baik berlatih.
Stephen Rauch
Mengapa downvote? Jawaban saya adalah alternatif yang dapat diterima, dan, seperti komentar mengatakan, praktik yang lebih baik.
NonCreature0714
1
Sebagian besar orang yang memilih tidak juga berkomentar, jadi meminta penjelasan tentang suara turun jarang akan memberi Anda penjelasan, karena pemilih yang turun sudah pergi dan tidak mungkin kembali. Saya sarankan Anda menghapus kode yang diketik yang tidak berfungsi dari jawaban Anda. Saya akan bersedia memberikan suara jika Anda meluangkan waktu untuk membersihkannya dan menjelaskan mengapa $()ini adalah praktik yang lebih baik.
Stephen Rauch
Seperti yang dijelaskan Stephen kepada Anda, 'bukan `. Anda harus merangkum dengan command, tetapi ini sudah usang. menggunakan $ () lebih baik, karena enkapsulasi $ ($ (perintah)) jauh lebih mudah dan tidak perlu melarikan diri khusus. Maka itu lebih disukai. Pada contoh pertama Anda menggunakan tanda kutip biasa, maka readlink mencoba menemukan file bernama 'yang java' dengan spasi dalam namanya. Tapi maksud Anda adalah perintah panggilan yang dengan argumen java, untuk menemukan jalur executable biner java.
Znik
0

Pada MAC OX, "-f" parameter tidak berfungsi, 'readlink' berfungsi tanpa parameter apa pun.

KZs-MacBook-Pro:bin kz$ readlink -f pip3
readlink: illegal option -- f
usage: readlink [-n] [file ...]

KZs-MacBook-Pro:bin kz$ readlink pip3
../../../Library/Frameworks/Python.framework/Versions/3.7/bin/pip3
Xb74Dkjb
sumber