Bir klasördeki tüm bağlantıların kesilmesi


10

Sabit bağlantıları olan (aynı klasörde veya başka bir yerde) belirli sayıda dosya içeren bir klasörünüz var ve bu dosyaların bağımsızlığını kaldırmak istiyorum, böylece bağımsız hale geliyorlar ve içeriklerindeki değişiklikler herhangi bir şeyi etkilemeyecek diğer dosya (bağlantı sayısı 1 olur).

Aşağıda, temel olarak her bir sabit bağlantıyı başka bir konuma kopyalayan, sonra yerine geri taşıyan bir çözüm veriyorum.

Ancak bu yöntem oldukça kaba ve hata eğilimli görünüyor, bu yüzden bir dosyayı benim için hardlink bağlayacak bazı komut olup olmadığını bilmek istiyorum.

Kaba cevap:

Sabit bağlantıları olan dosyaları bulma ( Düzen : Sabit bağlantıları olan soketleri vb. Bulmak için find -not -type d -links +1) kullanın :

find      -type f -links +1 # files only
find -not -type d -links +1 # files, sockets etc.

Bir dosyanın bağlantısını kaldırmak için kaba bir yöntem (başka bir konuma kopyalayın ve geri taşıyın): Düzenleme: Celada'nın dediği gibi, zaman damgalarını ve izinleri kaybetmemek için aşağıda bir cp -p yapmak en iyisidir. Düzenleme: Geçici bir dizin oluşturun ve geçici bir dosyanın üzerine yazmak yerine altındaki bir dosyaya kopyalayın, mvkomut hala riskli olsa da (teşekkürler @Tobu) bazı verilerin üzerine yazma riskini en aza indirir . Düzenleme: Aynı dosya sisteminde geçici dizini oluşturmaya çalışın (@MikkoRantalainen).

# This is unhardlink.sh
set -e
for i in "$@"; do
  temp="$(mktemp -d -- "${i%/*}/hardlnk-XXXXXXXX")"
  [ -e "$temp" ] && cp -ip "$i" "$temp/tempcopy" && mv "$temp/tempcopy" "$i" && rmdir "$temp"
done

(Yani, tüm sabit bağlantıları un-hardlink Düzenleme : değişmiş -type fiçin -not -type d, yukarıya bakınız):

find -not -type d -links +1 -print0 | xargs -0 unhardlink.sh

Bu 'kaba' düşünmezdim. Bunu daha hızlı almanın tek yolu muhtemelen sendfile () sistem çağrısı ile biraz hile yapmak ve açık kaynak dosyasının bağlantısını kaldırmak ve hedefi yerinde yeniden yazmaktır. Açıkçası onun çabaya değer değil.
Matthew Ife

Ben kullanarak bu komutu çalıştırdığınızda 'ham', ben demek, örneğin, cp -ianahtar, onu geçersiz kılmak gerektiğini soran bana birkaç mesajlar tükürdü ./fileXXXXXX( $temp, tmpfile benzersiz dosya adları vermelidir rağmen dosyası) orada böylece şırası bir çeşit yarış koşulu ya da her neyse ve bununla birlikte bazı verileri kaybetme riski.
Suzanne Dupéron

1
Dosyanın mevcut olması normal, sadece tempfile ile oluşturdunuz (nb: mktemp lehine kullanımdan kaldırıldı, ancak sorununuza neden olan bu değil).
Tobu

1
Bağlantısının unhardlink.shkaldırılması gereken dosyayı içeren aynı dizinde geçici bir dizin oluşturmanız gerekir. Aksi takdirde, özyinelemeli çağrınız başka bir dosya sistemi içinde geri çekilebilir ve geçici dizininiz geçerli çalışma dizininde olduğundan, dosya sistemi sınırları üzerinde bir şeyler taşırsınız. Bunun "$(dirname "$i")/hardlink-XXXXXX"yerine mktemp'e argüman olarak geçebilirsiniz.
Mikko Rantalainen

1
@MikkoRantalainen Çok teşekkürler, güncellendi! Dosya sistemi bir tür sendika veya fusedosya sistemi ise, aslında bundan path/to/hardlink-XXXfarklı bir fiziksel depolama ortamına gönderilebileceğini path/to/original-file, ancak bununla ilgili yapılabilecek çok şey olmadığını unutmayın.
Suzanne Dupéron

Yanıtlar:


9

Komut dosyanızda iyileştirme için yer vardır, örneğin komutun bağlantısız bırakma işleminde izinlerin ve zaman damgalarının korunması için bir -pseçenek cpeklemek ve bir hata durumunda geçici dosyanın silinmesi için bir miktar hata işleme ekleyebilirsiniz, ancak çözümünüzün temel fikri işe yarayacak tek fikirdir. Bir dosyanın bağlantısını kaldırmak için kopyalamanız ve ardından kopyayı orijinal adının üzerine taşımanız gerekir. "Daha az ham" bir çözüm yoktur ve başka bir işlemin dosyaya aynı anda erişmesi durumunda bu çözümün yarış koşulları vardır.


Aslında, her şeyi korumak, sembolik bağlantıları sembolik olarak kopyalamak için her zaman cp -a kullanırım. Bu sefer neden unuttuğumu bilmiyorum, ancak cevabınızı gördükten sonra, tüm zaman damgalarımı berbat ettiğimi ve onları bir yedeklemeden kurtarmak zorunda olduğumu anladım.
Suzanne Dupéron

5

Disk alanını yakmak istiyorsanız ve nispeten modern bir sürümüne sahipseniz tar(örneğin, Ubuntu 10.04 ve CentOS 6'da ne varsa), --hard-dereferenceseçenekle oynayabilirsiniz .

Gibi bir şey:

$ cd /path/to/directory
$ ls -l *
bar:
total 12
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 1
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 3

foo:
total 12
-rw-rw-r-- 2 cjc cjc 3 May  6 19:07 1
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 4

(koştuğum yerde ln foo/[12] bar)

$ tar cvf /tmp/dereferencing.tar --hard-dereference .
$ tar xvf /tmp/dereferencing.tar
$ ls -l *
bar:
total 12
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 1
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 3

foo:
total 12
-rw-rw-r-- 1 cjc cjc 3 May  6 19:07 1
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 4

Man sayfasından:

   --hard-dereference
          follow hard links; archive and dump the files they refer to

Katranın yapamayacağı çok az şey olduğundan şüpheleniyorum. Güzel düzeltme.
Joseph Kern

Her şeyi kopyalamak için yeterli disk alanım olmadığını belirtmeyi unuttum. Temel olarak, yönteminiz cp -a --no-preserve=links /path/to/folder /path/to/copy && rm -rf /path/to/folder && mv /path/to/copy /path/to/folderyanılmıyorsam aynıdır . Yine de yönteminiz daha verimli olurdu, çünkü katran daha az disk araması, daha az daralma içerecektir. Bir cs yönteminden bile daha düşük performans ile, rsync ile aynı elde edilebilir :).
Suzanne Dupéron

1
Fazladan disk kullanmaktan kaçınmak için, benzer bir şey çalıştırmak mümkün olabilir, tar cvf - --hard-dereference . | tar xf -ancak bazı şeylerin patlamasına neden olacak bir yarış durumu olabilir. Ben denemedim ve şu anda bunu yapmak biraz hayal kırıklığına uğradım.
cjc
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.