Fractionner une grande arborescence de répertoires en morceaux de taille spécifiée?

11

J'ai une arborescence de répertoires que je voudrais sauvegarder sur des disques optiques. Malheureusement, il dépasse la taille de n'importe quel disque (environ 60 Go). Je suis à la recherche d'un script qui diviserait cet arbre en morceaux de taille appropriée avec des liens durs ou autres (laissant l'original intact). Je pourrais ensuite alimenter ces arbres de petite taille dans le processus de sauvegarde (ajouter une redondance PAR2, etc.).

Ce n'est pas un script sophistiqué, mais il semble que cela ait déjà été fait. Suggestions?

(Le fractionnement et l'écriture en une seule étape est un pas parce que je veux faire plus de choses avant que les fichiers ne soient brûlés.)

Reid
la source
Avez-vous pensé à obtenir un écrivain bluray?
bsd
2
Le support DVD n'est pas fiable ... Je recommanderais un lecteur externe, une sauvegarde en ligne comme Carbonite, ou si vous gravez un support, utilisez une certaine par2protection.
Aaron D. Marasco

Réponses:

7

Il existe une application conçue pour cela: dirsplit

Il vit généralement dans cdrkitou en dirsplitpaquets.

Il peut créer des dossiers prêts à l'emploi avec des liens pour créer facilement des DVD avec K3b ou un autre logiciel GUI

Hubert Kario
la source
Cela a très bien fonctionné. Dans Ubuntu, je l'ai trouvé dans le genisoimagepaquet.
nograpes
2

Une fois, j'ai fait un mauvais script dans un but similaire. C'est juste un coup de coude, mais quand je l'ai écrit, je me fichais du temps d'exécution ou de la beauté. Je suis sûr qu'il existe des versions plus "productifiées" du même concept, mais si vous souhaitez obtenir des idées ou quelque chose pour commencer à pirater, voici (l'a fait en 2008, alors utilisez-le à vos risques et périls!): - )

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

Je pense que j'ai eu le résultat partagé via la samba à un hôte Windows qui en a gravé des disques. Si vous utilisez ce qui précède sans modification, vous pouvez utiliser mkisofsun autre archiveur qui résout les liens symboliques.

MattBianco
la source
J'ai apporté quelques modifications à votre script pour gérer les caractères spéciaux dans les noms de fichiers (espace, tirets et points initiaux \[?*). Lecture suggérée: ne pas analyser la sortie de ls , $ VAR vs $ {VAR} et pour citer ou ne pas citer . Notez que je n'ai pas testé le script résultant. Si vous ne comprenez pas un de mes changements, n'hésitez pas à demander.
Gilles 'SO- arrête d'être méchant'
@ Gilles: J'ai fait beaucoup de lecture depuis 2008 ;-) Les changements pour rendre le script plus générique sont bons. (Je n'aime pas l'introduction de [par opposition à test, cependant) ...
MattBianco
Vous devez minuscule la plupart de ces variables. Par convention, nous capitalisons les variables d'environnement (PAGER, EDITOR, SHELL, ...) et les variables internes du shell. Tous les autres noms de variables doivent contenir au moins une lettre minuscule. Cette convention évite de remplacer accidentellement les variables environnementales et internes.
Chris Down
2

Une fois, j'ai écrit un script pour résoudre un problème similaire - je l'ai appelé "distribuer" (vous pouvez lire le code principal du script ou du fichier avec le message d'aide , ou le télécharger sous forme de package ); à partir de sa description :

distribuer - Distribuer une collection de packages sur plusieurs CD (particulièrement bon pour une utilisation future avec APT)

Description: le programme `distribuer 'facilite les tâches liées à la création d'un jeu de CD pour la distribution d'une collection de packages. Les tâches comprennent: disposer le système de fichiers CD (diviser la grande quantité de packages en plusieurs disques, etc.), préparer la collection pour une utilisation par APT (indexation), créer des images ISO et enregistrer les disques.

Des mises à jour périodiques de la collection initialement distribuée peuvent être publiées à l'aide de «distribuer».

Il effectue l'ensemble du processus en plusieurs étapes: à un stade, il crée les «dispositions» du disque à l'aide de liens symboliques vers les fichiers d'origine - afin que vous puissiez intervenir et modifier les futures arborescences de disque.

Les détails de son utilisation peuvent être lus dans le message d'aide imprimé par le script (ou en consultant le code source).

Il a été écrit avec un cas d'utilisation plus délicat à l'esprit (publier des mises à jour en tant que «diff» - l'ensemble de nouveaux fichiers ajoutés - à la collection de fichiers enregistrée à l'origine), il comprend donc une étape initiale supplémentaire, à savoir, «la correction "l'état actuel de la collection de fichiers (pour simplifier, il le fait en reproduisant la collection de fichiers d'origine au moyen de liens symboliques, dans un lieu de travail spécial pour enregistrer les états de la collection; puis, dans le futur, il pourra créer un diff entre un futur état actuel de la collection de fichiers et cet état enregistré). Ainsi, bien que vous n'ayez peut-être pas besoin de cette fonctionnalité, vous ne pouvez pas ignorer cette étape initiale, AFAIR.

De plus, je ne suis pas sûr maintenant (je l'ai écrit il y a quelques années) s'il traite bien les arbres complexes ou s'il est censé ne diviser que les répertoires de fichiers simples (à un niveau). (Veuillez vérifier le message d'aide ou le code source pour en être sûr; je le vérifierai aussi un peu plus tard, quand j'aurai du temps.)

Les éléments liés à APT sont facultatifs, alors ne faites pas attention à ce qu'ils puissent préparer des collections de packages à utiliser par APT si vous n'en avez pas besoin.

Si vous êtes intéressé, bien sûr, n'hésitez pas à le réécrire à vos besoins ou à suggérer des améliorations.

(Veuillez noter que le package comprend des correctifs utiles supplémentaires non appliqués dans la liste de codes présentée au référentiel Git lié ci-dessus!)

imz - Ivan Zakharyaschev
la source
J'ai présenté - entre autres choses - l'extrait de code distributequi résout la tâche essentielle demandée ici.
imz - Ivan Zakharyaschev
2

Nous ne devons pas oublier que l'essence de la tâche est en effet assez simple; comme mis dans un tutoriel sur Haskell (qui est écrit autour de l'élaboration de la solution pour cette tâche, progressivement améliorée)

Réfléchissons maintenant un instant au fonctionnement de notre programme et exprimons-le en pseudocode:

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

Semble raisonnable? J'ai pensé ainsi.

Simplifions un peu notre vie et supposons pour l'instant que nous allons calculer la taille des répertoires quelque part en dehors de notre programme (par exemple, avec " du -sb *") et lire ces informations depuis stdin.

(du guide des auto-stoppeurs à Haskell, chapitre 1 )

(De plus, dans votre question, vous aimeriez pouvoir modifier (modifier) ​​les dispositions de disque résultantes, puis utiliser un outil pour les graver.)

Vous pouvez réutiliser (adapter et réutiliser) une variante simple du programme de ce tutoriel Haskell pour fractionner votre collection de fichiers.

Malheureusement, dans l' distributeoutil que j'ai mentionné ici dans une autre réponse , la simplicité de la tâche de fractionnement essentielle n'est pas compensée par la complexité et le gonflement de l'interface utilisateur de distribute(car il a été écrit pour combiner plusieurs tâches; bien qu'il soit effectué par étapes, mais toujours combiné pas de la manière la plus propre à laquelle je pouvais penser maintenant).

Pour vous aider à utiliser son code, voici un extrait du code bash de distribute(à la ligne 380 ) qui sert à effectuer cette tâche "essentielle" de fractionnement d'une collection de fichiers:

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

( lire la suite après la ligne 454 )

Notez que la eatFilesfonction prépare les dispositions des futurs disques sous forme d'arbres où les feuilles sont des liens symboliques vers les vrais fichiers. Ainsi, il répond à votre exigence de pouvoir modifier les dispositions avant de les graver. L' mkisofsutilitaire a une option pour suivre les liens symboliques, qui est en effet utilisé dans le code de ma mkisofonction .

Le script présenté (que vous pouvez prendre et réécrire selon vos besoins, bien sûr!) Suit l'idée la plus simple: pour additionner les tailles des fichiers (ou, plus précisément, des packages dans le cas de distribute) juste dans l'ordre dans lequel ils ont été listés, don ne fais pas de réarrangements.

Le "Guide des Hitchhikers pour Haskell" prend le problème d'optimisation plus au sérieux et suggère des variantes de programme qui essaieraient de réorganiser les fichiers intelligemment, afin qu'ils s'adaptent mieux aux disques (et nécessitent moins de disques):

Assez de préliminaires déjà. allons emballer quelques CD.

Comme vous l'avez peut-être déjà reconnu, notre problème est classique. C'est ce qu'on appelle un "problème de sac à dos" ( google it up , si vous ne savez pas déjà ce que c'est. Il y a plus de 100000 liens).

commençons par la solution gourmande ...

(lire plus dans le chapitre 3 et plus loin.)

Autres outils intelligents

On m'a également dit que Debian utilise un outil pour rendre ses CD de distribution plus intelligents que mes distributecollections de paquets wrt: ses résultats sont plus agréables car il se soucie des dépendances inter-paquets et essaierait de rendre la collection de paquets qui fonctionne le premier disque fermé sous des dépendances, c'est-à-dire qu'aucun paquet du 1er disque ne devrait exiger un paquet d'un autre disque (ou du moins, je dirais, le nombre de ces dépendances devrait être minimisé).

imz - Ivan Zakharyaschev
la source
1

backup2l peut faire une grande partie de ce travail. Même si vous n'utilisez pas directement le package, vous pourriez en tirer des idées de script.

Randy Coulman
la source
0

L' rararchiveur peut être chargé de diviser automatiquement l'archive qu'il crée en morceaux d'une taille spécifique avec l' -vsizeindicateur.

Archivage de cette arborescence de répertoires nommée fooen morceaux de, disons, 500 mégaoctets chacun que vous spécifieriez
rar a backup.rar -v500m foo/

Shadur
la source
2
Que pourquoi rar? tar (+ bz2) + split est une approche plus native pour * nix.
rvs
Les "arbres de la taille d'une bouchée" ne sonnent pas tout à fait comme ça rar, à moins que vous ne décompactiez chaque "pièce" à nouveau dans son propre répertoire, ce qui bien sûr ne fonctionnera pas, car les pièces ne sont pas conçues comme ça, et ne sont pas divisées sur les limites des fichiers.
MattBianco
1
Si vous parlez d'outils qui donnent des résultats similaires à tar+ split, alors il y a aussi Dar ; voici la note sur sa fonctionnalité: "(SLICES) il a été conçu pour pouvoir fractionner une archive sur plusieurs supports amovibles quel que soit leur nombre et quelle que soit leur taille". Par rapport à tar+ split, je suppose qu'il permet des moyens plus faciles d'accéder aux fichiers archivés. (BTW, il a également une fonctionnalité ressemblant à distribute: "SAUVEGARDE DIFFÉRENTIELLE" & "INSTANTANÉ D'ARBRE DE RÉPERTOIRE", mais on peut ne pas aimer que le résultat soit un format spécial, pas un ISO avec un arbre dir.)
imz - Ivan Zakharyaschev