Sembolik Bağlantıları Dosyalarla Değiştirme


31

Tüm sembolik bağları, bağlandıkları dosyayla değiştirmenin kolay bir yolu var mı?


3
Ne problemi çözmeye çalışıyorsun?
Daniel Beck

3
Başka bir sürücüye bir sürü sembolik bağım var. Kaldırabilmem için, tüm dosyaları başka bir yere referans verilen sürücüden çıkarmam gerekiyor.
Marty Trenouth,

Yanıtlar:


14

"Easy" un bazı tanımları için:

#!/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

Bu betiği argümanlar olarak link isimleriyle, örneğin find . -type l -exec /path/tos/script {} +


2
Düzenlemek, anon için teşekkürler, ama senaryo yok gerekli tüm yerlerde değişkenleri alıntı yaparak, gayet güzel boşluklu sap dosya. Değişen "$var"için "${var}"sh / bash bir noop olduğunu. Bir bashism'i kaldırdım ( [[), gerisi POSIX sh ile uyumlu.
Grawity

Sembolik bağlantı arızalarını ele almak için daha sağlam bir yöntem cp, aynı dizindeki mv -fgeçici bir dosyaya, ardından bu geçici dosyayı orijinal haline getirmektir. Bu insanlar basılı gibi sorunlar karşı korumak gerekir Ctrl-Cveya dosya sistemi arasındaki dolduruyor rmve cp(böylece bile yeni engelleyen komutlar lnçalışmasını). Geçici dosya isimleri ls -a, gerektiğinde daha sonra temizlenmeleri için kolayca anlaşılabilir.
Bay Fooz,

Yan bir not olarak, neden sadece dava bloğu abstarget=$(readlink -f "$link")yerine neden kullanmadığımı hatırlayamıyorum , ancak taşınabilirlik sebepleri olabilirdi.
Grawity,

17

Verileri yeni bir dizine kopyalamak için sadece tar kullanmak daha kolay olabilir.

-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.

Böyle bir şey kullanabilirsin

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

1
Çözümünüzü seviyorum ama mesajınızın son bölümünü anlamıyorum. Benim için yapmanız gerekenler:tar -hcf - sourcedir | tar -xf - -C newdir
Seb DA ROCHA

1
Kabul edildi, bu cevabın yorum başına güncellenmesi gerekir.
astabada

1
cp -Lbasit bir çözümdür
plesiv

@ plesiv true ve posix uyumlu, ancak tüm cpuygulamalar dizinleri kopyalayamaz.
Wyatt8740

16

Eğer seni doğru anladıysam -L, cpkomutun bayrağı tam olarak istediğini yapmalıydı.

Sadece tüm sembolik linkleri kopyalayın, işaret ettikleri dosyalarla değiştirin.


4
Teşekkürler - neredeyse ihtiyacım olan şey: Yapmam gereken bir şey yapmak zorundaydım: cp -L files tmp/ && rm files && cp tmp/files . Eğer
adaçayı

5

"Kolay", büyük olasılıkla bir işlevi olacaktır.

Muhtemelen sembolik olarak bağlantılı dosyaları bulmak için "find" komut satırı yardımcı programını kullanan bir komut dosyası yazardım, sonra dosyayı kaldırmak ve değiştirmek için rm ve cp'yi çağırır. Ayrıca, sym linkini de hareket ettirmeden önce yeterli boş alan olup olmadığını kontrol ederek find eyleminin çağrılması için de iyi iş çıkarırsınız.

Başka bir çözüm, söz konusu dosya sistemini, sym linklerini gizleyen bir şey (samba gibi) üzerine monte etmek olabilir, ardından sadece her şeyi kopyalayın. Ancak birçok durumda, bunun gibi bir şey diğer sorunları da beraberinde getirir.

Sorunuza daha doğrudan bir cevap muhtemelen "evet" dir.

Düzenleme: Daha spesifik bilgi isteğine göre Bulunacak man sayfasına göre , bu komut tüm sym link dosyalarını / dizininde 2 dizin derinliğinde listeleyecektir:

find / -maxdepth 2 -type l -print

( bu burada bulundu )

Bulmak için bir şeyi yürütmek üzere bulmak için:

find / -maxdepth 2 -type l -exec ./ReplaceSymLink.sh {} \;

Yeni oluşturduğum komut dosyasını arayacağına ve yeni bulduğun dosya adını gireceğine inanıyorum. Alternatif olarak, dosyaya bulma çıktısını yakalayabilir ("find [blah]> symlinks.data", vb. Kullanın), ardından bu dosyayı orijinal bir şekilde zarifçe kopyalamayı işlemek için yazdığınız bir komut dosyasına geçirin.


? Biraz genel - ayrıntılı olabilir misiniz?
Linker3000,

2
Sözdizimi-exec ./ReplaceSymLink.sh {} \;
Grawity

Bu öğeleri bulmak ve cevap olarak işaretli olanı bulmak için bağlantılar kullanılır!
Marty Trenouth,

3

Bu, kullandığım oneliner: tüm yerel dosyaların "kaynak" içerisindeki başka bir dosyaya bağlantılar olduğunu varsayalım. Dosya seçimini desenlerle daraltabilir veya "bul". Lütfen kullanmadan önce anlayın.

f * için; cp --remove-hedef kaynak / $ f $ f; tamam

Bu yardımcı olur umarım


readlink kullanımı nasıl olur: f için *; cp ---- remove-destination "$ (readlink $ f)" "$ f"; bitmiş
Diego

Evet, bu iyi bir fikir, ancak operasyon üzerindeki kontrolünü kaybediyorsunuz. Çözümümün bir sınırı, ortasında boşluk bulunan dosyalar için veya çok uzun listelerde işe yaramamasıdır. Muhtemelen nihai çözüm, yukarıdaki 'find --exec' i 'hedefi kaldır' ile bir araya getirmektir. Denemek isteyen var mı?
MastroGeppetto

Ortadaki boşluklar çift fıkraya "$ f" koyarak hafifletilmelidir. İşte "for loop" yerine "find & xargs" ile nasıl kullanıyorum: find. } ")" {} "'Görünürlük için ayrı bir cevap olarak gönderdim. superuser.com/a/1329543/499386
Diego

2
find . -type l -exec cp --dereference --recursive '{}' '{}'.dereferenced \;

Bağlantılı her dosya / klasörün bir kopyasını oluşturacaktır <filename>.dereferenced, bu sadece doğrudan değiştirmekten daha güvenlidir (daha az uygunsa). Kopyalanan verileri sembolik bağlantıların dosya adlarına taşımak, okuyucunun alıştırması olarak bırakılmıştır.


2

Önceki fikirlerden bazılarını kullanarak, aşağıdaki komut tekrarlayan bir şekilde her link bağlantısını orijinalinin bir kopyasıyla değiştirir:

find . -type l -exec bash -c "echo 'Replacing {} ...';  cp -LR '{}' '{}'.dereferenced;  rm '{}';  mv '{}'.dereferenced '{}'" \;


1

Orada çok iyi cevaplar var ama ben kolay bir şey aradığından beri

for i in *; do link=$(readlink $i) && rm $i && mv $link $i; done

Küçük bir geliştirme sembolik bağları bulmaya yardımcı olacaktır: lnk için `bul. tipi l`; do src = $ ($ lnk readlink) && rm $ lnk && mv $ src $ lnk; bitti (yine de hiyerarşi ile test edilmedi, backticks ile dikkatli olun)
Roman Susi

1

Normalde bağlantıyı takip edip dosyayı kopyalamayı beklediğinizde gwenview bağlantılarını kopyalarken de aynı sorunu yaşadım.

Tüm bağlantıları izleyerek ve tüm sivri dosyaları dizine kopyalayarak dizini 'temizlemek' için yaptığım, örneğin

"for file in `ls`; do cp -L $file scratchdir/$file; done; mv scratchdir/* ./" 

Bu bir komut dosyası koymak için çok tehlikeli çünkü kontrol yok ama sorunumu düzeltti.



0

Tek satırlı bir sürüm yaptım, çünkü web sitem bash scriptlerine izin vermedi ve benim için iyi çalıştı:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.