Büyük dizin ağacını belirtilen boyutlu parçalara bölmek?


11

Optik disklere yedeklemek istediğim bir dizin ağacı var. Ne yazık ki, herhangi bir diskin boyutunu aşıyor (yaklaşık 60GB). Ben sert ağaç ya da whatnot (orijinal el değmeden bırakarak) ile uygun büyüklükte parçalar halinde bu ağaç bölünecek bir komut dosyası arıyorum. Daha sonra bu ısırık boyutundaki ağaçları yedekleme işlemine besleyebilirim (PAR2 artıklığı vb. Ekleyin).

Süslü bir senaryo değil, ama zaten yapılmış gibi görünüyor. Öneriler?

(Tek adımda yayma ve yazma işlem bir işlem değildir çünkü dosyalar yakılmadan önce daha fazla şey yapmak istiyorum.)


Bluray yazarı almayı düşündünüz mü?
bsd

2
DVD ortamı güvenilir değil ... Harici bir sürücü, Carbonite gibi çevrimiçi bir yedekleme öneriyorum veya medya yazıyorsanız, biraz par2koruma kullanın .
Aaron D. Marasco

Yanıtlar:


7

Bunun için tasarlanmış bir uygulama var: dirsplit

Genellikle yaşayan cdrkitveya dirsplitpaketler.

K3b veya diğer GUI yazılımlarıyla kolayca DVD oluşturmak için kullanıma hazır klasörler oluşturabilir


Bu gerçekten işe yaradı. Ubuntu'da bunu genisoimagepakette buldum .
nograpes


2

Bir keresinde benzer bir amaç için çirkin bir senaryo hazırladım. Bu sadece bir çamur, ama yazdığımda, yürütme zamanı veya güzelliği umursamadım. Eminim aynı kavramın daha "ürün" sürümleri vardır, ama hack başlamak için bazı fikirler ya da bir şey almak istiyorsanız, işte gidiyor (2008 yılında yaptı, bu yüzden kendi sorumluluğunuzdadır kullanın!): - )

#!/bin/sh -
REPO=/export/foton/PictureStore
LINKS=/export/foton/links
SPLITTIX=`date '+%y%m%d-%H%M'`

# kilobytes
DVDSIZE=4400000
PARTPREFIX="DVD-"
REPOSIZE=`du -sk -- ${REPO} | awk '{print $1}'`
NUMPARTS=`expr $REPOSIZE / $DVDSIZE`
SPLITDIR=${LINKS}/splits/${SPLITTIX}
mkdir -p -- "$SPLITDIR"

PARTNUM=1
PARTSIZ=0
DONESIZ=0
PARTNUM=`echo $PARTNUM | awk '{printf("%03x", $0)}'`
mkdir -p -- "${SPLITDIR}/${PARTPREFIX}${PARTNUM}"
for D in "${REPO}"/..?* "${REPO}"/.[!.]* "${REPO}"/*
do
  if [ ! -e "$D" ]; then continue; fi  # skip ..?*, .[!.]* and * if there are no matching files
  D=${D#$REPO/}
  D_SIZ=`du -sk -- "${REPO}/$D" | awk '{print $1}'`
  if test `expr $D_SIZ + $PARTSIZ` -le $DVDSIZE
  then
    # link to D in this part
    ln -s -- "$REPO/$D" "${SPLITDIR}/${PARTPREFIX}${PARTNUM}/$D"
    # adjust counters
    PARTSIZ=`expr $PARTSIZ + $D_SIZ`
    DONESIZ=`expr $DONESIZ + $D_SIZ`
  else
    # next part and link to D in that
    echo PART $PARTNUM: $PARTSIZ kb '(target' $DVDSIZE 'kb)'
    PARTNUM=`expr $PARTNUM + 1`
    PARTNUM=`echo $PARTNUM | awk '{printf("%03x", $0)}'`
    PARTSIZ=$D_SIZ
    DONESIZ=`expr $DONESIZ + $D_SIZ`
    mkdir -p -- "${SPLITDIR}/${PARTPREFIX}${PARTNUM}"
    ln -s -- "$REPO/$D" "${SPLITDIR}/${PARTPREFIX}${PARTNUM}/$D"
  fi
done
echo "wrote $DONESIZ kb in $PARTNUM parts in $SPLITDIR"

Ben sonuç samba aracılığıyla ondan diskler yaktı bir windows host paylaştı düşünüyorum. Yukarıdakileri değiştirmeden kullanırsanız, mkisofssembolik bağlantıları çözen başka bir arşivleyici kullanmak isteyebilirsiniz .


Komut dosyasında dosya adlarında (boşluk, ilk tire ve noktalar, \[?*) özel karakterlerle başa çıkmak için birkaç değişiklik yaptım . Önerilen okuma: ls , $ VAR ve $ {VAR} çıktılarını ayrıştırmayın ve alıntı yapınız veya alıntı yapmayınız . Ortaya çıkan komut dosyasını test etmediğimi unutmayın. Değişikliklerimi anlamıyorsanız, sormaya çekinmeyin.
Gilles 'SO- kötü olmayı bırak

@Gilles: 2008'den beri çok fazla okuma yaptım ;-) Senaryoyu daha genel hale getirmek için yapılan değişiklikler iyi. (Ben [aksine aksine tanıtım hoşlanmıyorum test) ...
MattBianco

Bu değişkenlerin çoğunu küçük harflerle yazmalısınız. Geleneksel olarak, ortam değişkenlerini (PAGER, EDITOR, SHELL, ...) ve iç kabuk değişkenlerini aktifleştiriyoruz. Diğer tüm değişken adları en az bir küçük harf içermelidir. Bu sözleşme, çevresel ve dahili değişkenlerin yanlışlıkla geçersiz kılınmasını önler.
Chris Down

2

Bir keresinde benzer bir sorunu çözmek için bir komut dosyası yazdım - "dağıt" olarak adlandırdım ( komut dosyasının veya kodun yardım koduyla ana kodunu okuyabilir veya bir paket olarak indirebilirsiniz ); onun gelen açıklama :

dağıt - Bir paket koleksiyonunu birden fazla CD'ye dağıt (özellikle APT ile gelecekte kullanılmak üzere iyi)

Açıklama: `` dağıt '' programı, bir paket koleksiyonunun dağıtımı için bir CD seti oluşturmayla ilgili görevleri yapmayı kolaylaştırır. Görevler şunları içerir: CD dosya sisteminin düzenlenmesi (büyük miktardaki paketlerin birkaç diske bölünmesi vb.), Koleksiyonun APT (indeksleme) tarafından kullanılmak üzere hazırlanması, ISO görüntüleri oluşturulması ve disklerin kaydedilmesi.

İlk dağıtılan koleksiyona periyodik güncellemeler `` dağıt '' yardımıyla verilebilir.

Tüm süreci birkaç aşamada yapar: bir aşamada, orijinal dosyalara sembolik bağlantılar kullanarak furure diski "düzenleri" oluşturur - böylece gelecekteki disk ağaçlarına müdahale edebilir ve değiştirebilirsiniz.

Kullanımıyla ilgili ayrıntılar, komut dosyası tarafından yazdırılan yardım iletisinde (veya kaynak koduna bakarak) okunabilir.

Daha karmaşık bir kullanım durumu düşünülerek yazılmıştır (başlangıçta kaydedilen dosya koleksiyonuna "diff" - eklenen yeni dosyalar kümesi - güncellemeler yayınlamak), bu nedenle ek bir başlangıç ​​aşaması, yani "düzeltme" "dosya koleksiyonunun mevcut durumu (basitlik için, bunu, koleksiyonun durumlarını kaydetmek için özel bir çalışma yerinde, semboller yoluyla orijinal dosya koleksiyonunu çoğaltarak yapar; o zaman, gelecekte bir süre sonra, dosya koleksiyonunun gelecekteki geçerli durumu ile kaydedilen bu durum arasında fark oluşturabilir). Bu nedenle, bu özelliğe ihtiyacınız olmayabilir, ancak bu ilk aşamayı (AFAIR) atlayamazsınız.

Ayrıca, şimdi (birkaç yıl önce yazdım) karmaşık ağaçlara iyi davranıp davranmadığından mı yoksa dosyaların yalnızca düz (bir düzey) dizinlerini bölmesi mi gerektiğinden emin değilim. (Emin olmak için lütfen yardım mesajına veya kaynak koduna bakın; Biraz sonra biraz zamanım olduğunda da buna bakacağım.)

APT ile ilgili şeyler isteğe bağlıdır, bu yüzden ihtiyacınız yoksa APT tarafından kullanılacak paket koleksiyonları hazırlayabileceğine dikkat etmeyin.

Eğer ilgilenirseniz, elbette, ihtiyaçlarınıza yeniden yazmaktan çekinmeyin veya iyileştirmeler önerin.

(Lütfen pakette , yukarıda bağlanan Git deposunda sunulan kod listesine uygulanmayan ek faydalı ekler içerdiğine dikkat edin !)


Ben var sunulan --among başka şeyler - Kod alıntı gelen distributeesansiyel görev hakkında burada istedi çözer.
imz - Ivan Zakharyaschev

2

Unutmamalıyız ki, görevin özü aslında oldukça basittir; Haskell ile ilgili bir öğreticide belirtildiği gibi (bu göreve yönelik çözümün çalışılmasıyla yazılır, aşamalı olarak rafine edilir)

Şimdi bir an için programımızın nasıl çalışacağını düşünelim ve programı sahte kodda ifade edelim:

main = Read list of directories and their sizes.
       Decide how to fit them on CD-Rs.
       Print solution.

Kulağa makul geliyor mu? Ben de öyle düşünmüştüm.

Hayatımızı biraz basitleştirelim ve şimdilik programımızın dışında bir yerde (örneğin, " du -sb *" ile) dizin boyutlarını hesaplayacağımızı ve bu bilgileri stdin'den okuyacağımızı varsayalım .

( Otostopçu rehberinden Haskell, Bölüm 1 )

(Ayrıca, sorunuzda, ortaya çıkan disk düzenlerini değiştirebilir (düzenleyebilir) ve ardından bunları yazmak için bir araç kullanabilirsiniz.)

Dosya koleksiyonunuzu bölmek için o Haskell öğreticisinden programın basit bir varyantını yeniden kullanabilir (uyarlayabilir ve yeniden kullanabilirsiniz).

Ne yazık ki, içinde başka bir cevap burada bahsettiğimiz bu aracı , esansiyel bölme görevi basitliği kullanıcı arayüzünün karmaşıklığı ve kabarmışlığın eşleşmeyen birkaç görevleri birleştirmek için yazılmıştır çünkü (; aşamada gerçekleştirilir rağmen, ama yine de düşünebildiğim en temiz şekilde bir arada değil).distributedistribute

Kodundan biraz yararlanmanıza yardımcı olmak için, bir dosya koleksiyonunu bölmenin bu "temel" görevini gerçekleştirmeye yarayan distribute( satır 380'de ) bash kodundan bir alıntı :

# Splitting:

function splitMirrorDir() {
  if [[ ! -d "$THIS_BASES_DIR/$BASE/$type" ]]; then
    echo $"No base fixed for $type" >&2
    exit 1
  fi

  # Getting the list of all suitable files:
  local -a allFiles
  let 'no = 0' ||:
  allFiles=()
  # no points to the next free position in allFiles
  # allFiles contains the constructed list
  for p in "$THIS_BASES_DIR/$BASE/$type"/*.rpm; do
      if [[ ! -e "$p" ]]; then
      # fail on non-existent files
      echo $"Package file doesn't exist: " "$p" >&2
      return 1 
      fi
      if [[ "$ONLY_REAL_FILES" == "yes" && ! -f "$p" ]]; then
      continue
      fi
      if [[ "$DIFF_TO_BASE" ]]; then
          older_copy="$DIFF_TO_BASE/$type/${p##*/}" # using shell param expansion instead of `basename' to speed up
          if [[ -h "$older_copy" || -a "$older_copy" ]]; then
          continue
      fi
      fi
      allFiles[$(( no++ ))]="$p"
  done
  readonly -a allFiles

  # Splitting the list of all files into future disks:
  # 
  local -a filesToEat allSizes
  let 'no = 0' ||:
  filesToEat=()
  allSizes=($(getSize "${allFiles[@]}"))
  readonly -a allSizes
  # allSizes contains the sizes corrsponding to allFiles
  # filesToEat hold the constructed list of files to put on the current disk
  # no points to the next free position in filesToEat
  # totalSize should hold the sum of the sizes 
  #  of the files already put into filesToEat;
  #  it is set and reset externally.
  for p in "${allFiles[@]}"; do 
      if (( totalsize + ${allSizes[$(( no ))]} > CDVOLUME )); then
      eatFiles "${filesToEat[@]}"
          filesToEat=()
          finishCD
      startTypedCD
    fi
      let "totalsize += ${allSizes[$(( no ))]}" ||:
      filesToEat[$(( no++ ))]="$p"
  done
  eatFiles "${filesToEat[@]}"
}

function eatFiles() {
    #{ oldIFS="$IFS"; IFS=$'\n'; echo "$FUNCNAME: args: " "$*" | head >&2;  IFS="$oldIFS"; }
    zeroDelimited "$@" | xargs -0 --no-run-if-empty \
    cp -s \
    --target-dir="$THIS_LAYOUTS_DIR/cd$(( cdN ))/$PREFIX/$type$DOT_SUFFIX"/ \
    --
}

function startTypedCD() {
#  set -x
  mkdir -p "$THIS_LAYOUTS_DIR/cd$(( cdN ))/$PREFIX/$type$DOT_SUFFIX"
  start_action $" %s with %s" "$(( cdN ))" "$type"
#  set +x
}

function finishCD() {

( 454. satırdan sonra daha fazlasını okuyun )

eatFilesFonksiyonun, gelecekteki disklerin yerleşimlerini, yaprakların gerçek dosyalara sembolik olduğu ağaçlar olarak hazırladığını unutmayın . Bu nedenle, yazdırmadan önce düzenleri düzenleyebilmeniz gereksiniminizi karşılamaktadır. mkisofsYarar gerçekten kodunda kullanılır Sembolik takip için bir seçenek vardır benim mkisoişlevi .

Sunulan komut dosyası (elbette ihtiyaçlarınıza göre ve yeniden yazabilirsiniz!) En basit fikri takip eder: dosyaların boyutlarını (veya daha doğrusu, paketlerdeki paketleri distribute) sadece listelendikleri sırayla toplamak için , herhangi bir yeniden düzenleme yapmayın.

"Otostopçunun Haskell rehberi" optimizasyon problemini daha ciddiye alır ve disklere daha iyi uymaları (ve daha az disk gerektirmeleri) için dosyaları akıllıca yeniden düzenlemeye çalışacak program varyantlarını önerir:

Zaten yeterince ön hazırlık. hadi bazı CD'leri paketleyelim.

Zaten fark etmiş olabileceğiniz gibi, sorunumuz klasik bir sorundur. Buna "sırt çantası sorunu" denir ( zaten ne olduğunu bilmiyorsanız google it up . 100000'den fazla bağlantı var).

açgözlü çözümden başlayalım ...

( Bölüm 3 ve daha fazlasında daha fazla bilgi edinin .)

Diğer akıllı araçlar

Ayrıca Debian'ın benim distributewrt paket koleksiyonumdan daha akıllı olan dağıtım CD'lerini yapmak için bir araç kullandığı söylendi : sonuçları daha iyi çünkü paketler arası bağımlılıkları önemsiyor ve paketlerin toplanmasını yapmaya çalışıyor ilk disk bağımlılıklar altında kapatılır, yani 1. diskteki hiçbir paket başka bir diskten bir paket gerektirmez (ya da en azından söyleyebilirim, bu tür bağımlılıkların sayısı en aza indirilmelidir).


1

backup2l bu işin çoğunu yapabilir. Paketi doğrudan kullanmasanız bile, komut dosyası fikirleri alabilirsiniz.


0

rarArşiv otomatik olarak bir belirli boyutun parçaları içine yaratır arşiv bölmek için talimat edilebilir -vsizebayrak.

Adında belirtilen dizin ağacını foo, örneğin belirttiğiniz 500 megabaytlık parçalar halinde arşivleme
rar a backup.rar -v500m foo/


2
Neden rar? tar (+ bz2) + split, * nix için daha doğal bir yaklaşımdır.
rvs

"Isırık büyüklüğündeki ağaçlar", rarher "parçayı" tekrar kendi dizinine açmadıkça, kulağa hoş gelmiyor , bu da elbette işe yaramayacak, çünkü parçalar böyle tasarlanmadı ve dosya sınırlarına bölünmedi.
mattbianco

1
tar+ splitBenzeri sonuçlar veren araçlar hakkında konuşuyorsanız , dar ; ilgili özelliğiyle ilgili not: "(DİLİMLER) bir arşiv, sayıları ne olursa olsun ve boyutları ne olursa olsun çıkarılabilir bir çok medyaya bölünmek üzere tasarlanmıştır." tar+ İle karşılaştırıldığında split, arşivlenen dosyalara erişmenin daha kolay yollarına izin verdiğini düşünüyorum. (BTW, aynı zamanda benzer bir özelliğe sahiptir distribute: "DİFERANSİYEL YEDEKLEME" & "DİREKTİF AĞACI SNAPSHOT", ancak sonuç özel bir biçimdir, dir ağacı olan bir ISO değildir.)
imz - Ivan Zakharyaschev
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.