디스크에 백업하고 싶은 디렉토리 트리가 있습니다. 불행하게도 두 디스크의 크기(약 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 튜토리얼의 간단한 프로그램 변형을 재사용(적응 및 재사용)하여 파일 모음을 분할할 수 있습니다.
불행히도,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() {
이 eatFiles
기능은 향후 디스크의 레이아웃을 트리로 준비하며, 리프는 실제 파일에 대한 심볼릭 링크입니다. 따라서 굽기 전에 요구 사항에 맞게 레이아웃을 편집할 수 있어야 합니다. 이 mkisofs
유틸리티에는 코드에서 실제로 사용되는 심볼릭 링크를 추적하는 옵션이 있습니다.내 mkiso
기능.
제공된 스크립트(물론 필요에 따라 재정의할 수 있음!)는 가장 간단한 아이디어를 따릅니다. distribute
즉, 나열된 순서대로 파일 크기(더 정확하게는 패키지의 경우)를 찾습니다. 어떤 재배열도 하지 마세요.
"하스켈을 사용하는 히치하이커를 위한 안내서"에서는 최적화 문제를 더욱 심각하게 다루며 파일이 디스크에 더 잘 맞도록(그리고 더 적은 디스크를 필요로 하도록) 영리하게 파일을 재배열하는 프로그램의 변형을 권장합니다.
사전 준비는 충분합니다. CD를 좀 챙기러 가자.
당신도 알고 있듯이, 우리의 문제는 고전적인 문제입니다. 그것은 알려져있다"배낭 문제" (구글해봐, 아직 그것이 무엇인지 모른다면. 링크 수는 100,000개가 넘습니다.)
탐욕스러운 솔루션부터 시작해 보겠습니다.
(더 읽어보세요3 장그리고 더. )
기타 스마트 도구
또한 데비안은 내 wrt 패키지 컬렉션보다 더 스마트한 배포 CD를 만들기 위해 도구를 사용한다고 들었습니다 distribute
. 그 결과는 패키지 간의 종속성을 고려하고 실행할 패키지 컬렉션을 만들려고 시도하기 때문에 더 좋습니다. 첫 번째 디스크는 종속성에 따라 닫힙니다. 즉, 첫 번째 디스크의 어떤 패키지도 다른 디스크의 패키지를 요구해서는 안 됩니다(또는 적어도 그러한 종속성의 수는 최소화되어야 한다고 말하고 싶습니다).