Czy dzielisz duże drzewo katalogów na fragmenty o określonym rozmiarze?


11

Mam drzewo katalogów, które chciałbym utworzyć na dyskach optycznych. Niestety przekracza rozmiar dowolnego dysku (około 60 GB). Szukam skryptu, który podzieliłby to drzewo na kawałki o odpowiedniej wielkości z twardymi linkami lub czymkolwiek innym (pozostawiając oryginał nietknięty). Mogę następnie wprowadzić te drzewa wielkości kęsa do procesu tworzenia kopii zapasowej (dodaj redundancję PAR2 itp.).

To nie jest wymyślny scenariusz, ale wygląda na to, że mógł już być zrobiony. Propozycje?

(Łączenie i pisanie w jednym kroku jest nie do uniknięcia, ponieważ chcę robić więcej rzeczy, zanim pliki zostaną wypalone).


Czy zastanawiałeś się nad pisaniem bluray?
bsd

2
Nośniki DVD są niewiarygodne ... Poleciłbym zewnętrzny dysk, kopię zapasową online, taką jak Carbonite, lub jeśli nagrywasz nośniki, użyj par2ochrony.
Aaron D. Marasco,

Odpowiedzi:


7

Istnieje aplikacja przeznaczona do tego: dirsplit

Zwykle mieszka w cdrkitlub w dirsplitpaczkach.

Może tworzyć gotowe do użycia foldery z linkami do łatwego tworzenia płyt DVD za pomocą K3b lub innego oprogramowania GUI


To działało naprawdę dobrze. W Ubuntu znalazłem to w genisoimagepakiecie.
nograpes


2

Kiedyś napisałem brzydki scenariusz do podobnego celu. To tylko kludge, ale kiedy to napisałem, nie przejmowałem się czasem wykonania ani ładnością. Jestem pewien, że jest więcej „produkowanych” wersji tej samej koncepcji, ale jeśli chcesz uzyskać jakieś pomysły lub coś, co możesz zacząć hakować, oto (zrób to w 2008 roku, więc użyj na własne ryzyko!): - )

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

Wydaje mi się, że wyniki zostały udostępnione przez sambę hostowi Windows, który nagrał z niej dyski. Jeśli korzystasz z powyższego niezmienionego, możesz użyć mkisofsinnego archiwizatora, który rozpoznaje dowiązania symboliczne.


Wprowadziłem kilka zmian w twoim skrypcie, aby radzić sobie ze znakami specjalnymi w nazwach plików (białe znaki, początkowe myślniki i kropki \[?*). Sugerowana lektura: nie analizuj wyników ls , $ VAR vs $ {VAR} i cytuj lub nie cytuj . Zauważ, że nie przetestowałem wynikowego skryptu. Jeśli nie rozumiesz jednej z moich zmian, możesz zapytać.
Gilles „SO- przestań być zły”

@Gilles: Dużo czytałem od 2008 roku ;-) Zmiany, które sprawiają, że skrypt jest bardziej ogólny, są dobre. (Nie [test
podobają

Większość tych zmiennych powinna zawierać małe litery. Zgodnie z konwencją, kapitalizujemy zmienne środowiskowe (PAGER, EDITOR, SHELL, ...) i wewnętrzne zmienne powłoki. Wszystkie pozostałe nazwy zmiennych powinny zawierać co najmniej jedną małą literę. Konwencja ta pozwala uniknąć przypadkowego zastąpienia zmiennych środowiskowych i wewnętrznych.
Chris Down,

2

Kiedyś napisałem skrypt, aby rozwiązać podobny problem - nazwałem go „rozpowszechniać” (możesz przeczytać główny kod skryptu lub plik z komunikatem pomocy lub pobrać go jako pakiet ); z jego opisu :

rozpowszechniać - rozpowszechniać kolekcję pakietów na wielu płytach CD (szczególnie dobre do użycia w przyszłości z APT)

Opis: program `distribute 'ułatwia wykonywanie zadań związanych z tworzeniem zestawu płyt CD do dystrybucji kolekcji pakietów. Zadania obejmują: układanie systemu plików płyt CD (dzielenie dużej ilości pakietów na kilka płyt itp.), Przygotowywanie kolekcji do wykorzystania przez APT (indeksowanie), tworzenie obrazów ISO i nagrywanie płyt.

Okresowe aktualizacje początkowo dystrybuowanej kolekcji można wydawać za pomocą programu `distribute '.

Cały proces przebiega w kilku etapach: na jednym etapie tworzy „układy” dysku furure przy użyciu dowiązań symbolicznych do oryginalnych plików - dzięki czemu można interweniować i zmieniać przyszłe drzewa dysków.

Szczegóły dotyczące jego użycia można odczytać w komunikacie pomocy wydrukowanym przez skrypt (lub poprzez sprawdzenie kodu źródłowego).

Został napisany z myślą o trudniejszym przypadku użycia (wydawanie aktualizacji jako „diff” - zestawu dodanych nowych plików - do pierwotnie nagranej kolekcji plików), więc zawiera jeden dodatkowy etap początkowy, a mianowicie „naprawianie” „bieżący stan kolekcji plików (dla uproszczenia robi to poprzez replikację oryginalnej kolekcji plików za pomocą dowiązań symbolicznych w specjalnym miejscu pracy do zapisywania stanów kolekcji; następnie, w przyszłości, będzie w stanie stworzyć różnicę między przyszłym bieżącym stanem zbioru plików a tym stanem zapisanym). Tak więc, chociaż możesz nie potrzebować tej funkcji, nie możesz pominąć tego początkowego etapu, AFAIR.

Ponadto nie jestem teraz pewien (napisałem to kilka lat temu), czy dobrze traktuje złożone drzewa, czy też ma podzielić tylko zwykłe (jeden poziom) katalogi plików. (Aby się upewnić, przejrzyj komunikat pomocy lub kod źródłowy; ja też to sprawdzę, nieco później, kiedy będę miał trochę czasu).

Rzeczy związane z APT są opcjonalne, więc nie zwracaj uwagi, że może przygotować kolekcje pakietów do użycia przez APT, jeśli nie jest to potrzebne.

Jeśli jesteś zainteresowany, oczywiście możesz przepisać go do swoich potrzeb lub zasugerować ulepszenia.

(Proszę zwrócić uwagę, że pakiet zawiera dodatkowe użyteczne łatki, które nie zostały zastosowane w prezentowanym wykazie kodów w linku do repozytorium Git powyżej!)


Mam przedstawiony --among innych rzeczy - ten fragment kodu z distributektóry rozwiązuje podstawowym zadaniem poproszony o tutaj.
imz - Ivan Zakharyaschev

2

Nie powinniśmy zapominać, że istota zadania jest rzeczywiście dość prosta; jak w tutorialu o Haskell (który jest napisany na temat pracy nad rozwiązaniem dla tego zadania, stopniowo udoskonalany)

Zastanówmy się teraz przez chwilę, jak nasz program będzie działał, i wyrażmy to w pseudokodzie:

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

Brzmi rozsądnie? Tak myślałem.

Uprośćmy trochę nasze życie i załóżmy na razie, że obliczymy rozmiary katalogów gdzieś poza naszym programem (na przykład za pomocą „ du -sb *”) i odczytamy te informacje ze standardowego wejścia.

(z przewodnika Autostopowiczów po Haskell, rozdział 1 )

(Dodatkowo w swoim pytaniu chciałbyś mieć możliwość dostosowania (edycji) powstałych układów dysków, a następnie skorzystania z narzędzia do ich wypalenia).

Możesz ponownie użyć (dostosować i ponownie użyć) prostego wariantu programu z tego samouczka Haskell do dzielenia kolekcji plików.

Niestety, w tym distributenarzędzia, które już wspomniano tu w innej odpowiedzi , prostota zasadniczego zadania łupania nie towarzyszy złożoności i bloatedness w interfejsie użytkownika distribute(ponieważ został napisany aby połączyć kilka zadań, chociaż wykonywane etapami, ale nadal łączy się nie w najczystszy sposób, jaki mógłbym teraz wymyślić).

Aby pomóc ci w pewnym stopniu wykorzystać jego kod, oto fragment kodu bash distribute(w linii 380 ), który służy do wykonania tego „niezbędnego” zadania dzielenia kolekcji plików:

# 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() {

( czytaj więcej po linii 454 )

Zauważ, że eatFilesfunkcja przygotowuje układy przyszłych dysków jako drzewa, w których liście są dowiązaniami symbolicznymi do rzeczywistych plików. Tak więc spełnia twoje wymagania, abyś mógł edytować układy przed nagraniem. mkisofsNarzędzie ma możliwość śledzić dowiązania symboliczne, które rzeczywiście jest stosowany w kodzie mojej mkisofunkcji .

Prezentowany skrypt (który możesz oczywiście zabrać i przepisać zgodnie z własnymi potrzebami!) Podąża za najprostszym pomysłem: zsumować rozmiary plików (a dokładniej w przypadku pakietów distribute) dokładnie w kolejności, w jakiej zostały wymienione. nie rób żadnych zmian.

„Przewodnik autostopowiczów po Haskell” poważniej traktuje problem optymalizacji i sugeruje warianty programów, które próbowałyby inteligentnie zmienić rozmieszczenie plików, aby lepiej pasowały do ​​dysków (i wymagały mniejszej liczby dysków):

Już wystarczająco dużo wstępnych kwalifikacji. chodźmy spakować trochę płyt CD.

Jak już zapewne zauważyliście, nasz problem jest klasyczny. Nazywa się to „problemem plecakowym” ( google go w górę , jeśli jeszcze nie wiesz, co to jest. Istnieje ponad 100000 linków).

zacznijmy od chciwego rozwiązania ...

(czytaj więcej w rozdziale 3 i dalszych.)

Inne inteligentne narzędzia

Powiedziano mi również, że Debian korzysta z narzędzia, które sprawia, że ​​jego dyski CD są mądrzejsze niż moje distributekolekcje wrt pakietów: jego wyniki są ładniejsze, ponieważ dba o zależności między pakietami i próbowałby stworzyć kolekcję pakietów, która działa na pierwszy dysk jest zamknięty w zależnościach, tzn. żaden pakiet z pierwszego dysku nie powinien wymagać pakietu z innego dysku (lub, przynajmniej powiedziałbym, liczbę takich zależności należy zminimalizować).


1

backup2l może wykonać wiele z tej pracy. Nawet jeśli nie używasz pakietu bezpośrednio, możesz uzyskać od niego kilka pomysłów na skrypt.


0

rarArchiwum może być pouczeni, aby automatycznie podzieli archiwum tworzy się na kawałki o wielkości określonej z -vsizeflagą.

Archiwizowanie tego drzewa katalogów nazwanego foona kawałki, powiedzmy, 500 megabajtów za sztukę, które określisz
rar a backup.rar -v500m foo/


2
Niż dlaczego rar? tar (+ bz2) + split to bardziej natywne podejście do * nix.
rvs

„drzewa wielkości kęsa” nie do końca brzmią rar , chyba że rozpakujesz ponownie każdą „część” do własnego katalogu, co oczywiście nie będzie działać, ponieważ części nie są tak zaprojektowane i nie są dzielone na granicach plików.
MattBianco,

1
Jeśli mówimy o narzędziach, które dają wyniki podobne do tar+ split, to jest też dar ; oto uwaga na temat jego istotnej funkcji: „(SLICES) został zaprojektowany, aby móc dzielić archiwum na kilka nośników wymiennych, niezależnie od ich liczby i wielkości”. Zakładam, że w porównaniu z tar+ splitpozwala na łatwiejszy dostęp do zarchiwizowanych plików. (BTW, ma również funkcję przypominającądistribute : „DIFFERENTIAL BACKUP” i „DIRECTORY TREE SNAPSHOT”, ale nie może się podobać, że wynik jest specjalnym formatem, a nie ISO z drzewem katalogów.)
imz - Ivan Zakharyaschev
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.