temukan semua tautan simbolik di pohon direktori yang menunjuk ke luar pohon itu

8

Saya sering memindahkan pohon direktori ke lokasi lain atau menyalin tarbal mereka ke komputer lain, dan saya ingin memiliki metode untuk memeriksa apakah ada symlink di pohon direktori A menunjuk ke lokasi di luar A karena ini akan rusak dalam dipindahkan / disalin direktori.

Marcus Junius Brutus
sumber

Jawaban:

7

Anda ingin sebuah program bernama realpath, digunakan bersama dengan find.

Misalnya:

find . -type l -exec realpath {} \; | grep -v "^$(pwd)"
bahamat
sumber
1
Mantra yang Anda berikan hanya melaporkan lokasi target yang menyinggung, bukan symlink yang menunjukkannya. Karena itu saya telah menghapus penerimaan saya. Silakan lihat "jawaban" saya di bawah: unix.stackexchange.com/a/308899/24044 dan jika Anda senang dengan itu (atau memperbaikinya) saya akan menghapus "jawaban" saya dan menerima pertanyaan Anda lagi.
Marcus Junius Brutus
2

Gunakan bindf untuk membuat tampilan lain dari pohon direktori itu.

mkdir /tmp/view
bindfs /some/directory /tmp/view

Kemudian gunakan utilitas symlinks (dikirimkan oleh banyak distribusi, atau kompilasi dari sumber ) untuk mendeteksi tautan lintas sistem file.

symlinks -r /tmp/view | sed -n 's/^\(absolute\|other_fs\): //p'

(Perhatikan bahwa mem-parsing output mengasumsikan bahwa tautan simbolik Anda dan targetnya tidak mengandung baris baru, juga jalur ke tautan simbolik tidak mengandung substring tersebut  -> .) Utilitas yang sama itu juga dapat mengonversi symlink absolut menjadi relatif (tetapi Anda ingin melakukannya dari lokasi asli).

Gilles 'SANGAT berhenti menjadi jahat'
sumber
2

Dengan zsh:

cd -P -- "$dir"
for i (**/*(ND@)) [[ $i:A = $PWD/* ]] || [[ $i:A = $PWD ]] || print -r -- "$i => $i:A"

Sekarang, jika direktori tersebut /foodan Anda memiliki /foo/barsymlink /foo/baz, itu adalah tautan yang targetnya ada di / foo, tetapi begitu dipindahkan, tautan tersebut akan tetap rusak, jadi Anda mungkin ingin juga mencocokkan symlink dengan jalur absolut.

Tetapi meskipun demikian, bar => ../foo/bazin /fooakan menjadi masalah (false negative), begitu juga di a => bmana bsymlink berada di luar pohon (false positive, tergantung pada bagaimana Anda ingin melihatnya)

Stéphane Chazelas
sumber
2

Saya harus mengubah sedikit jawaban yang diberikan oleh @bahamat untuk membuatnya bekerja.

Versi yang disediakan hanya melaporkan lokasi absolut yang menyinggung tetapi bukan symlink yang menunjuk ke sana.

Inilah yang saya gunakan (saya yakin itu bisa diperbaiki):

for f in $(find . -type l ); do echo -n $(realpath $f) && echo -n "|" && echo $f ; done | grep -v "^$(pwd)" | cut -d \| -f 2 
Marcus Junius Brutus
sumber
Saya menemukan ini sebagai skrip yang paling berguna: for f in $(find . -type l); do echo $(realpath -m -q $f) '<-' $f; done | grep-v "^$(pwd)"(terutama -mdan -qyang menyaring tautan yang rusak dan non-eksternal)
Adam Lindberg
1

GNU coreutils terbukti realpath, yang menyelesaikan symlink. Dengan ini, Anda dapat membandingkan target setiap symlink dengan direktori kerja saat ini dengan sesuatu seperti:

#!/bin/bash

find . | while read filename
do
  if realpath $filename | grep -E "^$PWD" > /dev/null
  then
    echo 'this file is safe'
  else
    echo 'this file links externally'
  fi
done
titik dua
sumber
Beberapa masalah: tidak -type l, tidak ada -ropsi untuk read, IFS tidak dibersihkan read, $filenametidak dikutip, $PWDdiperlakukan sebagai ekspresi reguler, jalur dengan karakter baris baru yang tidak diperhitungkan, /foobarakan dicocokkan dengan $PWD== "/ foo"
Stéphane Chazelas