Saya memiliki banyak tautan simbolik ke drive lain. Saya perlu memindahkan semua file dari drive yang dirujuk di tempat lain sehingga saya dapat menghapusnya.
Marty Trenouth
Jawaban:
14
Untuk beberapa definisi "mudah":
#!/bin/shset-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 {} +
Terima kasih untuk mengedit, anon, tapi script tidak menangani nama file dengan spasi baik-baik saja, dengan mengutip variabel di semua tempat yang diperlukan. Mengubah "$var"ke "${var}"adalah noop di sh / bash. Saya menghapus satu bashism ( [[), sisanya kompatibel dengan POSIX sh.
grawity
Metode yang bahkan lebih kuat untuk menangani kegagalan symlink adalah cpdengan membuat file sementara di direktori yang sama kemudian mv -ffile sementara itu menjadi yang asli. Ini harus melindungi dari masalah seperti orang yang menahan Ctrl-Catau sistem file yang mengisi antara perintah rmdan cp(sehingga mencegah bahkan yang baru lnbekerja). Nama file sementara mudah dikenali ls -auntuk pembersihan nanti jika diperlukan.
Tuan Fooz
Sebagai catatan tambahan, saya benar-benar tidak dapat mengingat mengapa saya tidak hanya menggunakan abstarget=$(readlink -f "$link")bukan case case , tetapi itu mungkin merupakan alasan portabilitas.
grawity
17
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
Saya suka solusi Anda, tetapi saya tidak mengerti bagian terakhir dari pesan Anda. Bagi saya, Anda harus melakukan:tar -hcf - sourcedir | tar -xf - -C newdir
Seb DA ROCHA
1
Setuju, jawaban ini perlu diperbarui sesuai komentar.
astabada
1
cp -Ladalah solusi yang lebih sederhana
plesiv
@plesiv true, dan posix-compliant, tetapi tidak semua cpimplementasi akan menyalin direktori.
Wyatt8740
16
Jika saya mengerti Anda dengan benar -Lbendera cpperintah harus melakukan apa yang Anda inginkan.
Cukup salin semua symlink dan itu akan menggantinya dengan file yang mereka tuju.
Terima kasih - hampir apa yang saya butuhkan: Saya harus melakukan sesuatu seperti: cp -L files tmp/ && rm files && cp tmp/files . Jika Anda mengklarifikasi, Anda mungkin akan membantu lebih banyak orang ...
bijak
5
"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 /:
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.
Ini untuk mencari item dan yang ditandai sebagai jawaban digunakan untuk mengganti tautan!
Marty Trenouth
3
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
bagaimana menggunakan readlink: for f in *; jangan cp ---- hapus-tujuan "$ (readlink $ f)" "$ f"; selesai
Diego
Ya, itu ide yang bagus, tetapi Anda kehilangan kontrol pada operasi. Salah satu batasan dari solusi saya adalah tidak berfungsi untuk file yang kosong di tengah, atau untuk daftar yang sangat panjang. Mungkin solusi terakhir adalah menyatukan 'find --exec' di atas dengan 'remove destination'. Adakah yang mau mencoba?
MastroGeppetto
kosong di tengah harus dikurangi dengan menempatkan "$ f" dalam tanda kutip. Inilah cara saya menggunakannya dengan "find & xargs" alih-alih "for loop": find ./ -type l -print0 | xargs -0 -n1 -i sh -c 'cp --hapus-tujuan $ (readlink "{ } ")" {} "'Saya telah mempostingnya sebagai jawaban terpisah untuk visibilitas. superuser.com/a/1329543/499386
Diego
2
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.
Sedikit peningkatan akan membantu menemukan tautan simbolik: untuk lnk di `find. -tipe l`; do src = $ (readlink $ lnk) && rm $ lnk && mv $ src $ lnk; selesai (tidak diuji dengan hierarki, hati-hati dengan backticks)
Roman Susi
1
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.
Jawaban:
Untuk beberapa definisi "mudah":
Jalankan skrip ini dengan nama tautan sebagai argumen, misalnya melalui
find . -type l -exec /path/tos/script {} +
sumber
"$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 kemudianmv -f
file sementara itu menjadi yang asli. Ini harus melindungi dari masalah seperti orang yang menahanCtrl-C
atau sistem file yang mengisi antara perintahrm
dancp
(sehingga mencegah bahkan yang baruln
bekerja). Nama file sementara mudah dikenalils -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.
Anda bisa menggunakan sesuatu seperti ini
sumber
tar -hcf - sourcedir | tar -xf - -C newdir
cp -L
adalah solusi yang lebih sederhanacp
implementasi akan menyalin direktori.Jika saya mengerti Anda dengan benar
-L
benderacp
perintah harus melakukan apa yang Anda inginkan.Cukup salin semua symlink dan itu akan menggantinya dengan file yang mereka tuju.
sumber
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 /:
( ini ditemukan di sini )
Untuk mendapatkan temukan untuk mengeksekusi sesuatu pada menemukannya:
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.
sumber
-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.
Semoga ini membantu
sumber
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.sumber
Menggunakan beberapa ide sebelumnya, perintah berikut akan secara rekursif mengganti setiap symlink dengan salinan aslinya:
sumber
berdasarkan https://superuser.com/a/1301199/499386 dari MastroGeppetto
sumber
Ada banyak jawaban bagus di sana tetapi saya karena Anda mencari sesuatu yang mudah
sumber
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.
ini terlalu berbahaya untuk dimasukkan ke dalam skrip karena tidak ada pemeriksaan tetapi ini memperbaiki masalah saya.
sumber
sumber
Saya membuat versi satu baris, karena hotel web saya tidak mengizinkan skrip bash dan itu berfungsi dengan baik untuk saya:
sumber