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.

gerrit
sumber

Jawaban:

61

Opsi lain adalah menggunakan perintah yang dirancang khusus readlinkjika tersedia.

Misalnya

$ readlink -f `command -v php`
/usr/bin/php7.1
nikitautiu
sumber
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.

Coroos
sumber
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".

gerrit
sumber
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
Stéphane Chazelas
sumber
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.

rakslice
sumber
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}"
}
Léa Gris
sumber
0

realpathperintah coreutilspaket,

sebagaimana ditautkan dalam readlinkhalaman buku panduan perintah.


sebagai contoh:

realpath /bin/python

output

/usr/bin/python2.7

di mesin saya.


sumber