큰 디렉토리 트리를 지정된 크기의 청크로 분할하시겠습니까?

큰 디렉토리 트리를 지정된 크기의 청크로 분할하시겠습니까?

디스크에 백업하고 싶은 디렉토리 트리가 있습니다. 불행하게도 두 디스크의 크기(약 60GB)를 초과합니다. 나는 이 트리를 하드 링크 등을 사용하여 적절한 크기의 덩어리로 분할할 수 있는 스크립트를 찾고 있습니다(원본은 그대로 유지). 그런 다음 이러한 작은 트리를 백업 프로세스에 공급할 수 있습니다(PAR2 중복성 추가 등).

화려한 대본은 아니지만 아마도 완성되었을 것 같습니다. 제안?

(파일이 굽기 전에 더 많은 작업을 수행하고 싶기 때문에 한 단계에서 스패닝 및 쓰기가 작동하지 않습니다.)

답변1

이를 위해 설계된 응용 프로그램이 있습니다.dirsplit

cdrkit일반적으로 포장 이나 포장에서 발견됩니다 dirsplit.

K3b 또는 기타 GUI 소프트웨어를 사용하여 쉽게 DVD를 만들 수 있는 링크가 포함된 즉시 사용 가능한 폴더를 생성합니다.

답변2

당신은 또한 시도할 수 있습니다부분, 내가 작성한 도구(BSD 라이센스): https://sourceforge.net/projects/fpart/

답변3

나는 비슷한 목적으로 추악한 스크립트를 만든 적이 있습니다. 그저 패치워크일 뿐이지만, 제가 썼을 때는 실행 시간이나 미적인 측면을 고려하지 않았습니다. 동일한 컨셉의 "프로덕션 준비" 버전이 더 많이 있을 것이라고 확신하지만, 해킹을 시작할 수 있는 아이디어나 무언가를 얻고 싶다면 다음을 참조하세요(2008년에 제작되었으므로 위험 부담은 본인이 감수하고 사용하십시오!). -)

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

디스크를 구운 Windows 호스트에 Samba를 통해 결과를 공유한 것 같습니다. 위의 내용을 변경하지 않고 사용하는 경우 또는 심볼릭 링크를 해결하는 다른 아카이버를 사용할 수 있습니다 mkisofs.

답변4

우리는 Haskell 튜토리얼(이 작업에 대한 솔루션 작업을 중심으로 작성되었으며 점차적으로 개선됨)에 명시된 대로 작업의 성격이 실제로 단순하다는 점을 잊어서는 안 됩니다.

이제 우리 프로그램이 어떻게 실행되고 의사 코드로 표현되는지 생각해 봅시다.

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

합리적으로 들리나요? 나는 그렇게 생각했다.

du -sb *우리 삶을 조금 단순화하고 프로그램 외부 어딘가에서(예를 들어 " "를 사용하여) 디렉토리 크기를 계산하고 표준 입력에서 이 정보를 읽는다고 가정해 보겠습니다 .

(에서Haskell의 히치하이킹 가이드, 1장)

(또한 귀하의 질문에 따라 결과 디스크 레이아웃을 조정(편집)한 다음 도구를 사용하여 구울 수 있기를 원합니다.)

Haskell 튜토리얼의 간단한 프로그램 변형을 재사용(적응 및 재사용)하여 파일 모음을 분할할 수 있습니다.

불행히도,distribute다른 답변에서 언급한 도구, 기본적으로 작업 분할의 단순성은 사용자 인터페이스의 복잡성 및 부풀림과 일치하지 않습니다 distribute(여러 작업을 결합하도록 작성되었기 때문에 단계적으로 수행하는 동안 지금 당장 생각할 수 있는 가장 깔끔한 방식은 아닙니다). .

이를 최대한 활용하는 데 도움이 되도록 다음은 bash 코드의 일부입니다 distribute(위치:380라인)은 파일 모음을 분할하는 "기본" 작업을 수행하는 데 사용됩니다.

# 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행 이후에 자세히 읽어보세요.)

eatFiles기능은 향후 디스크의 레이아웃을 트리로 준비하며, 리프는 실제 파일에 대한 심볼릭 링크입니다. 따라서 굽기 전에 요구 사항에 맞게 레이아웃을 편집할 수 있어야 합니다. 이 mkisofs유틸리티에는 코드에서 실제로 사용되는 심볼릭 링크를 추적하는 옵션이 있습니다.mkiso기능.

제공된 스크립트(물론 필요에 따라 재정의할 수 있음!)는 가장 간단한 아이디어를 따릅니다. distribute즉, 나열된 순서대로 파일 크기(더 정확하게는 패키지의 경우)를 찾습니다. 어떤 재배열도 하지 마세요.

"하스켈을 사용하는 히치하이커를 위한 안내서"에서는 최적화 문제를 더욱 심각하게 다루며 파일이 디스크에 더 잘 맞도록(그리고 더 적은 디스크를 필요로 하도록) 영리하게 파일을 재배열하는 프로그램의 변형을 권장합니다.

사전 준비는 충분합니다. CD를 좀 챙기러 가자.

당신도 알고 있듯이, 우리의 문제는 고전적인 문제입니다. 그것은 알려져있다"배낭 문제" (구글해봐, 아직 그것이 무엇인지 모른다면. 링크 수는 100,000개가 넘습니다.)

탐욕스러운 솔루션부터 시작해 보겠습니다.

(더 읽어보세요3 장그리고 더. )

기타 스마트 도구

또한 데비안은 내 wrt 패키지 컬렉션보다 더 스마트한 배포 CD를 만들기 위해 도구를 사용한다고 들었습니다 distribute. 그 결과는 패키지 간의 종속성을 고려하고 실행할 패키지 컬렉션을 만들려고 시도하기 때문에 더 좋습니다. 첫 번째 디스크는 종속성에 따라 닫힙니다. 즉, 첫 번째 디스크의 어떤 패키지도 다른 디스크의 패키지를 요구해서는 안 됩니다(또는 적어도 그러한 종속성의 수는 최소화되어야 한다고 말하고 싶습니다).

관련 정보