Temukan hanya tujuan symlink


50

Untuk digunakan dalam skrip shell, saya mencari cara baris perintah untuk mendapatkan tujuan tautan simbolik. Yang paling dekat saya sejauh ini adalah stat -N src, yang keluaran src -> dst. Tentu saja saya dapat mengurai output dan mendapatkan dst, tetapi saya ingin tahu apakah ada cara langsung untuk mendapatkan tujuan.

Jawaban:


61

Opsi lain adalah menggunakan perintah yang dirancang khusus readlinkjika tersedia.

Misalnya

$ readlink -f `command -v php`
/usr/bin/php7.1

21
Gunakan readlink -fjika Anda ingin mengetahui target symlink terakhir dan tidak hanya yang berikutnya .
scai

Poin bagus! Lupa itu.
nikitautiu

11
Perhatikan bahwa itu -fadalah ekstensi non-portabel ke GNU readlink.
bahamat

2
Kapan tautan baca tidak tersedia? Terima kasih.
tommy.carstensen

2
@ tommy.carstensen readlink (1) telah ditambahkan ke GNU coreutils pada tahun 2003, jadi hari ini Anda mungkin dapat bergantung padanya pada hampir semua sistem yang menggunakan coreutils. ( Lih. Git.savannah.gnu.org/cgit/coreutils.git/commit/src/… )
Josip Rodin

16

Di Mac OS X dan FreeBSD / NetBSD / dll. nya:

stat -f %Y <filename>

Secara lebih umum saya kira solusinya adalah (stat --printf =% N menggunakan kutipan aneh):

ls -l b | sed -e 's/.* -> //'

Contoh:

# ln -s a b
# stat -f %Y b
a

Metode lain adalah:

# find b -maxdepth 0 -printf %l
a#

Baris terakhir hancur karena tidak memiliki baris baru, tetapi itu bagus jika Anda membutuhkan hasil dalam variabel, seperti itu

# f=$(find b -maxdepth 0 -printf %l)
# echo $f
a

The -maxdepthdiperlukan untuk mencegah finddari turun ke direktori jika bterjadi menjadi sebuah direktori.


Saya benar-benar membaca sepintas lalu, stat --printf='%N\n'persis seperti yang saya inginkan, kutipan aneh tidak mengganggu saya, mereka adalah kutipan yang sama rm dan ln
ThorSummoner

Ini rupanya tidak portabel karena di Linux, stat GNU coreutils '(1) memiliki parameter yang berbeda dan dicetak link -> destdalam output. Solusi find (1) harus diperiksa apakah itu dengan GNU findutils atau lainnya ...
Josip Rodin

Tolong jangan lupa mengutip ekspansi variabel Anda, echo $ftentu saja tidak menghasilkan apa yang Anda harapkan ketika symlink menunjuk ke /*(ya itu mungkin)
Camusensei

3

Hal ini dapat dilakukan dengan menggunakan GNU find: find src -prune -printf "%l\n".


1

Portable: tidak beruntung kecuali menggunakan heuristik untuk mem-parsing output ls-l, atau gunakan perl -le 'print readlink("some-file")'

beberapa sistem memiliki readlinkperintah, beberapa dengan -fopsi untuk mendapatkan jalur absolut.

Ada berbagai implementasi statperintah sebagai pembungkus untuk panggilan sistem stat/ lstat. GNU satu tidak berguna dalam hal itu, tetapi zsh's builtin satu lebih dari itu:

zmodload zsh/stat
stat +link the-link

Masih dengan zsh, Anda bisa mendapatkan path absolut dari file (menghapus setiap komponen symlink) dengan :Apengubah (berlaku untuk ekspansi variabel, ekspansi sejarah, dan globbing:

~$ gstat -c %N b
`b' -> `a'
~$ var=b
~$ echo $var:A
/home/me/a
~$ echo b(:A)
/home/me/a
~$ echo ?(@:A)
/home/me/a

1

Pada sistem di mana saya tidak punya readlinkatau statperintah tapi aku punya Python 2.x, saya menggunakan script singkat:

#!/usr/bin/env python

import os, sys

if __name__ == "__main__":
    src = sys.argv[1]
    target = os.readlink(src)
    if not os.path.isabs(target):
            target = os.path.abspath(os.path.join(os.path.dirname(src), target))
    print target

Perhatikan bahwa tidak seperti readlink -fini, hanya dapat mengikuti satu tingkat symlink.


1

Portable Bash realpath murni

bash_realpath() {
  # print the resolved path
  # @params
  # 1: the path to resolve
  # @return
  # &1: the resolved link path

  local path="${1}"
  while [[ -L ${path} && "$(ls -l "${path}")" =~ -\>\ (.*) ]]
  do
    path="${BASH_REMATCH[1]}"
  done
  echo "${path}"
}

0

realpathperintah coreutilspaket,

sebagaimana ditautkan dalam readlinkhalaman buku panduan perintah.


sebagai contoh:

realpath /bin/python

output

/usr/bin/python2.7

di mesin saya.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.