Her dosya için sabit bağlantılar kullanarak yinelenen bir dizini kopyalama


52

Her dosyanın asıl dosyaya bağlantı oluşturduğu bir dizin ağacının "kopyasını" oluşturmak istiyorum

Örnek: Bir dizin yapısına sahibim:

dirA/
dirA/file1
dirA/x/
dirA/x/file2
dirA/y/
dirA/y/file3

Beklenen sonuç, her dosyanın orijinal dosyaya bağlandığı dizin ağacının bir "kopyası":

dirB/            #  normal directory
dirB/file1       #  hardlink to dirA/file1
dirB/x/          #  normal directory
dirB/x/file2     #  hardlink to dirA/x/file2
dirB/y/          #  normal directory
dirB/y/file3     #  hardlink to dirA/y/file3

Yanıtlar:


50

Linux'ta (daha kesin olarak GNU ile ve genellikle çekirdek olarak Linux bulunan sistemlerde bulunan busyboxuygulamaların uygulanmasıyla cp) ve son zamanlarda FreeBSD ile, şu şekilde:

cp -al dirA dirB

Daha taşınabilir bir çözüm için, Stéphane Chazelas'ın pax ve cpio'larını kullanarak cevaba bakınız.


paxFreeBSD'de olduğu gibi , bağlantı cp -alinklerinin sabit olmadığını da unutmayın.
Stéphane Chazelas

Sabit bağlantıların ayrı dosya sistemi bağları arasında çalışmadığını unutmayın.
Dave

24

POSIXly seçeneği paxile okuma + yazma modunda kullanırsınız -l:

pax -rwlpe -s /A/B/ dirA .

( -peGNU gibi, kopyalanan bu durumda tüm dosyaları olası özellik (sadece dizinleri) korur cp'ın -ayapar).

Şimdi, standart olsa da , bu komut mutlaka çok taşınabilir değildir .

İlk olarak, çoğu GNU / Linux tabanlı sistem paxvarsayılan olarak içermez (isteğe bağlı olmayan bir POSIX yardımcı programı olmasına rağmen).

Daha sonra, birkaç uygulamayla birlikte bazı hatalar ve uygunsuzluklar bu kodla ilgili bir takım sorunlara neden olmaktadır.

  • bir hata nedeniyle, Solaris 10 paxkullanıldığında (en azından) çalışmıyor -rwlile kombinasyon halinde -s. Bazı nedenlerden dolayı ikame işlemi hem orijinal hem de kopyalanmış yola uygular. Yani yukarıda, link("dirB/file", "dirB/file")yerine bazı yapmaya çalışacaktı link("dirA/file", "dirB/file").
  • FreeBSD'de symlinkpax türündeki dosyalar için hardlinks oluşturmaz (POSIX tarafından izin verilen bir davranış). Sadece bu değil, ama aynı zamanda yollarda bazı hedeflere ikame (bir davranışı uygular değil POSIX tarafından izin verilir). Yani bir varsa örneğin symlink içinde , bu olacak içinde .foo -> AAdirAfoo -> BAdirB

Ayrıca, aynı şeyi ancak içeriğinde depolanan $srcve rasgele dosya yollarıyla yapmak istiyorsanız , içerideki tam dizin yapısını (var olması ve bir dizin olması gerektiğini) yarattığını $dstanlamak önemlidir . Örneğin, eğer bir halde, oluşturulur.pax -rwl -- "$src" "$dst"$src$dst$srcfoo/bar$dst/foo/bar

Bunun yerine, $dstbir kopyasını olmak istiyorsanız $src, en kolay muhtemelen olarak yapmaktır:

absolute_dst=$(umask 077 && mkdir -p -- "$dst" && cd -P -- "$dst" && pwd -P) &&
(cd -P -- "$src" && pax -rwlpe . "$absolute_dst")

(Bu aynı zamanda yukarıda belirtilen sorunların çoğunun etrafında da çalışacaktır ancak $dstyeni satır karakterlerinde mutlak sonlar sona ererse başarısız olur ).

Şimdi bu, GNU / Linux sistemlerinde hiçbir şeyin olmadığı yerlerde yardımcı olmaz pax.

Ve komutlarının paxözelliklerini birleştirmek için POSIX tarafından oluşturulduğunu not etmek ilginçtir .tarcpio

cpioa, tarihsel POSIX buluşa zıt olarak (1977) Unix komut ve hem de bir GNU uygulama (bir olduğu paxbir). Bu yüzden artık standart bir komut olmasa da (SUSv2'deydi), hala çok yaygındır ve genellikle güvenebileceğiniz temel bir dizi özellik vardır.

Eşdeğeri pax -rwlolur cpio -pl. Ancak:

  1. cpio argümanların tersine stdin'deki girdi dosyalarının listesini alır (newline ile sınırlandırılmış newline karakterleri desteklenmez.
  2. Tüm dosyalar belirtilmelidir (tipik olarak, bunun çıktısını beslersiniz find( findve cpioaynı kişiler tarafından ortaklaşa geliştirilmiştir)).
  3. meta veriler korunmaz (bazı cpiouygulamaların bazılarını korumaya yönelik seçenekleri vardır, ancak taşınabilir bir şey yoktur).

Yani ile cpio:

absolute_dst=$(umask 077 && mkdir -p -- "$dst" && cd -P -- "$dst" && pwd -P) &&
(cd -P -- "$src" && find . | cpio -pl "$absolute_dst")

-S / A / B / örneğime özgü görünüyor. Kaynak dizin adı ve hedef dizin adı, $ sourcedir ve $ targetdir değişkenleri olsaydı bunu nasıl yapardınız?
Gudmundur Orn

@GudmundurOrn, bkz. Düzenleme.
Stéphane Chazelas 11:15

OS X'te bu komutu çalıştırıyorum ve sadece "pax: .a.xt dosyasını kendine bağlayamıyorum" hata mesajını alıyorum. Komutunuzu tam anlamıyla kullandım, sadece kaynak dizini asıl adıyla değiştirerek, / A / B ve son noktayı olduğu gibi değiştirdim. Bir şeyi yanlış mı anlıyorum?
db,

@db, -s /A/Byerini Aile Bo kadar dirAolur dirB. Kaynak dizininizde adı yoksa A, bu işlem kendisini kopyalar (bağlar). Muhtemelen daha iyi yaklaşımlar için cevabın geri kalan kısmına da bakınız.
Stéphane Chazelas

6

Kısa cevap:

cd $source_folder
pax -rwlpe . $dest_folder

2

Dosyalarınızın bir kısmının (hepsinin veya bir kısmının) anlık görüntülerini veya yedeklemelerini yapmak için bu bağlantıyı kopyala özelliğini arıyorsanız rsnapshot.


1
İlginç. Ancak sanırım dosyalar değiştirilmeyecekse sabit bağlantılar sadece iyi bir anlık görüntü mekanizmasıdır. Sağ?
Gudmundur Orn

@Gudmundur Orn; Doğru. Cevabımda belirtilen araç, dosyaların benzersiz olduğu şekilde yeni bir anlık görüntü oluşturacaktır; yani varolan (değiştirilmemiş) dosyalar, hardlinkler olarak oluşturulacak ve yeni dosyalar (veya varolan dosyaların değiştirilmiş versiyonları) yeni dosyalar olarak oluşturulacaktır. Böylece sonuçta en az fazlalığa sahip olacaksınız.
Janis

0

@ gudmundur-orn'in cevabı doğrudur, ancak Linux üzerinde BtrFS kullanıyorsanız cp a --reflink=auto dirA dirB, hileyi yapmanız gerekir, farkla dosyalar aslında farklıdır ve birini değiştirmek diğerini değiştirmez. cp -cAPFS ile bir Mac ile çoğunlukla aynı elde edebilirsiniz ( automümkün değilse tam bir kopya yapar -c, başarısız olur).

Herhangi bir COW dosya sistemi bunu yapabilmelidir, ancak satıcılar standart bir komut satırı seçeneğinde anlaşamadılar.

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.