Apakah ada cara mudah untuk mengganti semua tautan simbolik dengan file yang ditautkannya?
Apakah ada cara mudah untuk mengganti semua tautan simbolik dengan file yang ditautkannya?
Jawaban:
Untuk beberapa definisi "mudah":
#!/bin/sh
set -e
for link; do
test -h "$link" || continue
dir=$(dirname "$link")
reltarget=$(readlink "$link")
case $reltarget in
/*) abstarget=$reltarget;;
*) abstarget=$dir/$reltarget;;
esac
rm -fv "$link"
cp -afv "$abstarget" "$link" || {
# on failure, restore the symlink
rm -rfv "$link"
ln -sfv "$reltarget" "$link"
}
done
Jalankan skrip ini dengan nama tautan sebagai argumen, misalnya melalui find . -type l -exec /path/tos/script {} +
"$var"
ke "${var}"
adalah noop di sh / bash. Saya menghapus satu bashism ( [[
), sisanya kompatibel dengan POSIX sh.
cp
dengan membuat file sementara di direktori yang sama kemudian mv -f
file sementara itu menjadi yang asli. Ini harus melindungi dari masalah seperti orang yang menahan Ctrl-C
atau sistem file yang mengisi antara perintah rm
dan cp
(sehingga mencegah bahkan yang baru ln
bekerja). Nama file sementara mudah dikenali ls -a
untuk pembersihan nanti jika diperlukan.
abstarget=$(readlink -f "$link")
bukan case case , tetapi itu mungkin merupakan alasan portabilitas.
Mungkin lebih mudah menggunakan tar untuk menyalin data ke direktori baru.
-H (c and r mode only) Symbolic links named on the command line will be followed; the target of the link will be archived, not the link itself.
Anda bisa menggunakan sesuatu seperti ini
tar -hcf - sourcedir | tar -xf - -C newdir
tar --help:
-H, --format=FORMAT create archive of the given format
-h, --dereference follow symlinks; archive and dump the files they point to
tar -hcf - sourcedir | tar -xf - -C newdir
cp -L
adalah solusi yang lebih sederhana
cp
implementasi akan menyalin direktori.
Jika saya mengerti Anda dengan benar -L
bendera cp
perintah harus melakukan apa yang Anda inginkan.
Cukup salin semua symlink dan itu akan menggantinya dengan file yang mereka tuju.
cp -L files tmp/ && rm files && cp tmp/files .
Jika Anda mengklarifikasi, Anda mungkin akan membantu lebih banyak orang ...
"Mudah" akan menjadi fungsi Anda, kemungkinan besar.
Saya mungkin akan menulis skrip yang menggunakan utilitas baris perintah "find" untuk menemukan file yang terhubung secara simbolis, kemudian memanggil rm dan cp untuk menghapus dan mengganti file. Anda mungkin sebaiknya melakukan tindakan yang disebut dengan find check bahwa ada ruang kosong yang tersisa sebelum memindahkan tautan sym juga.
Solusi lain mungkin dengan me-mount sistem file yang dimaksud melalui sesuatu yang menyembunyikan tautan sym (seperti samba), lalu salin semuanya dari itu. Tetapi dalam banyak kasus, sesuatu seperti itu akan menimbulkan masalah lain.
Jawaban yang lebih langsung untuk pertanyaan Anda mungkin "ya".
Sunting: Sesuai permintaan untuk info yang lebih spesifik. Menurut halaman manual untuk find , perintah ini akan mencantumkan semua file tautan sym ke kedalaman 2 direktori, dari /:
find / -maxdepth 2 -type l -print
Untuk mendapatkan temukan untuk mengeksekusi sesuatu pada menemukannya:
find / -maxdepth 2 -type l -exec ./ReplaceSymLink.sh {} \;
Saya yakin itu akan memanggil beberapa script yang baru saja saya buat, dan meneruskan nama file yang baru saja Anda temukan. Sebagai alternatif, Anda dapat menangkap output find ke file (gunakan "find [blah]> symlinks.data", dll) lalu berikan file itu ke skrip yang Anda tulis untuk menangani penyalinan di atas dokumen asli dengan anggun.
-exec ./ReplaceSymLink.sh {} \;
Ini adalah oneliner yang saya gunakan: menganggap semua file lokal adalah tautan ke file lain di "sumber". Anda dapat memperbaiki pemilihan file dengan pola atau "menemukan". Tolong, mengerti sebelum menggunakan.
untuk f di *; do cp --hapus sumber tujuan / $ f $ f; selesai
Semoga ini membantu
find . -type l -exec cp --dereference --recursive '{}' '{}'.dereferenced \;
Akan membuat salinan dari setiap file / folder yang disinkronkan <filename>.dereferenced
, yang lebih aman (jika kurang nyaman) daripada hanya menggantinya secara langsung. Memindahkan data yang disalin ke nama file symlink dibiarkan sebagai latihan untuk pembaca.
find ./ -type l -print0|xargs -0 -n1 -i sh -c 'cp --remove-destination $(readlink "{}") "{}" '
berdasarkan https://superuser.com/a/1301199/499386 dari MastroGeppetto
Ada banyak jawaban bagus di sana tetapi saya karena Anda mencari sesuatu yang mudah
for i in *; do link=$(readlink $i) && rm $i && mv $link $i; done
Saya memiliki masalah yang sama dengan tautan gwenview menyalin ketika Anda biasanya mengharapkannya untuk mengikuti tautan dan menyalin file.
Apa yang saya lakukan untuk 'membersihkan' direktori dengan mengikuti semua tautan dan menyalin semua file yang diarahkan ke direktori, adalah membuat direktori awal, jalankan mis.
"for file in `ls`; do cp -L $file scratchdir/$file; done; mv scratchdir/* ./"
ini terlalu berbahaya untuk dimasukkan ke dalam skrip karena tidak ada pemeriksaan tetapi ini memperbaiki masalah saya.
for f in *; do cp --remove-destination $(readlink "$f") "$f"; done
Saya membuat versi satu baris, karena hotel web saya tidak mengizinkan skrip bash dan itu berfungsi dengan baik untuk saya:
before:
> find . -type l | wc -l
358
> for link in `find . -type l` ; do echo "$link : "; ls -al $link ; cp $link notalink; unlink $link; mv notalink $link ; ls -al $link; done
...
after:
> find . -type l | wc -l
0