Saya memiliki sub-filesystem lengkap dalam jalur /home/user/system
yang berisi struktur Linux standar dengan direktori /bin
, /home
, /root
, /usr
, /var
, /etc
, ...
Sistem sub-file ini mengandung tautan simbolik, baik relatif maupun absolut. Symlink relatif baik-baik saja, mereka tetap berada di dalam sub-filesystem di bawah /home/user/system
. Tetapi symlink absolut bermasalah, karena mereka menunjuk ke target di luar sub-filesystem.
Sebagai contoh, kita mengasumsikan symlink absolut sebagai berikut (terlihat di dalam sub-filesystem):
/usr/file1 -> /usr/lib/file1
Dalam keseluruhan sistem file, kami memiliki tautan /home/user/system/usr/file1
yang sekarang mengarah ke file di /usr/lib/file1
luar sub-sistem file, alih-alih file /home/user/system/usr/lib/file1
di dalam sub-sistem file.
Saya ingin memiliki skrip sederhana, lebih disukai baris perintah tunggal (rsync, chroot, find, ...) yang mengubah setiap symlink absolut menjadi relatif.
Dalam contoh yang diberikan, tautan relatif itu akan menjadi
/usr/file1 -> ../usr/lib/file1
sumber
Jawaban:
Dengan
symlinks
utilitas oleh Mark Lord (ditawarkan oleh banyak distribusi; jika Anda tidak memilikinya, bangunlah dari sumber ):Atau, pada sistem yang memiliki
readlink
perintah dan-lname
predikat kefind
(peringatan: kode yang tidak diuji):sumber
_ {} +
di akhir penemuan? Juga, saya mendapatkan kesalahanfind: paths must precede expression: ksh
yang sepertinya tidak masuk akal (karena path mendahului ekspresi ksh)._
adalah$0
untuk potongan shell, dan{} +
digantikan oleh daftar argumen yang menjadi$1
,$2
, dll yangfor link; do …
loop atas (itu identik denganfor link in "$@"; do …
). Kesalahan darifind
ini karena kesalahan ketik (saya entah bagaimana berhasil mengetikkan backquotes alih-alih tanda kutip tunggal di sekitar argumen untuk-lname
).symlinks
? Ini akan menyelesaikan masalah Anda - pada dasarnya untuk apa ia dirancang (dengan kesal karena Anda harus menjalankannya chroot ( fakechroot harus melakukan triknya)).Bash murni & coreutils, mengubah symlink menjadi relatif tanpa
../
jalur yang tidak perlu :Anda dapat mengubah:
find .
untukfind /path/to/directory
mengkonversi symlink di direktori ituln -fs
untukecho ln -fs
untuk kering runPenjelasan:
target="$(realpath "$l")"
- Menemukan jalur absolut ke target symlinkln -fs
- membuat symlink (-s
), forcing (-f
) menulis ulang yang sudah adarealpath -s "$l"
- Menemukan jalur absolut ke symlink itu sendiridirname "$(realpath -s "$l")"
- Menemukan jalur absolut ke direktori yang berisi symlinkrealpath --relative-to="$(dirname "$(realpath -s "$l")")" "$target"
- Menemukan jalur target relatif ke symlink, dengan kata lain: mengkonversi absolut ke jalur relatifsumber
if
klausa untuk melewati tautan yang rusak.Cuplikan bash ini harus melakukannya. Formulir pertama akan mencetak apa yang akan dilakukan; yang kedua akan melakukannya. Saya akan hati-hati meninjau output karena merusak -
ln -f
menimpa tautan yang ada.sumber
Ini adalah solusi murni.
sumber
Mentransformasi absolut di tautan relatif didukung oleh sshfs yang memasang direktori jauh melalui ssh.
Perintahnya adalah: Ada
Perintah, terutama
<placeholders>
, harus disesuaikan dengan lingkungan spesifik.sumber