แยกต้นไม้ไดเรกทอรีขนาดใหญ่เป็นชิ้นขนาดที่ระบุหรือไม่


11

ฉันมีแผนผังไดเรกทอรีที่ฉันต้องการสำรองดิสก์แสง น่าเสียดายที่มันมีขนาดเกินกว่าดิสก์หนึ่งแผ่น (มีขนาดประมาณ 60GB) ฉันกำลังมองหาสคริปต์ที่จะแบ่งต้นไม้นี้เป็นชิ้นขนาดที่เหมาะสมด้วยการเชื่อมโยงอย่างหนักหรือ whatnot (ออกจากเดิมไม่มีใครแตะต้อง) ฉันสามารถป้อนต้นไม้ขนาดกัดเหล่านี้ลงในกระบวนการสำรองข้อมูล (เพิ่มความซ้ำซ้อน PAR2 และอื่น ๆ )

มันไม่ใช่สคริปต์แฟนซี แต่ดูเหมือนว่ามันอาจจะทำไปแล้ว ข้อเสนอแนะ?

(การขยายและการเขียนในขั้นตอนเดียวเป็นเรื่องไม่ต้องทำเพราะฉันต้องการทำสิ่งต่าง ๆ เพิ่มเติมก่อนที่ไฟล์จะถูกเบิร์น)


คุณคิดว่าจะเป็นนักเขียน bluray ไหม?
bsd

2
สื่อดีวีดีไม่น่าเชื่อถือ ... ฉันขอแนะนำไดรฟ์ภายนอกการสำรองข้อมูลออนไลน์เช่น Carbonite หรือหากการเขียนสื่อใช้par2การป้องกันบางอย่าง
Aaron D. Marasco

คำตอบ:


7

มีแอปพลิเคชันที่ออกแบบมาสำหรับสิ่งนี้: dirsplit

มันมักจะอาศัยอยู่ในcdrkitหรือdirsplitแพคเกจ

มันสามารถสร้างโฟลเดอร์ที่พร้อมใช้งานพร้อมลิงก์เพื่อสร้างดีวีดีได้อย่างง่ายดายด้วย K3b หรือซอฟต์แวร์ GUI อื่น ๆ


มันใช้งานได้ดีจริงๆ ใน Ubuntu ฉันพบมันในgenisoimageแพ็คเกจ
โน


2

ฉันเคยสร้างสคริปต์ที่น่าเกลียดเพื่อจุดประสงค์เดียวกัน มันเป็น kludge แต่เมื่อฉันเขียนมันฉันไม่สนใจเวลาดำเนินการหรือความน่ารัก ฉันแน่ใจว่ามีแนวคิดแบบเดียวกัน "productified" มากกว่าเดิม แต่ถ้าคุณต้องการที่จะได้รับความคิดหรือบางสิ่งบางอย่างที่จะเริ่มต้นการแฮ็คที่นี่ไป (ทำในปี 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 ที่เขียนแผ่นดิสก์จากมัน หากคุณใช้สิ่งที่ไม่เปลี่ยนแปลงด้านบนคุณอาจต้องการใช้mkisofsหรือผู้จัดเก็บอื่นที่แก้ไข symlink


ฉันได้ทำการเปลี่ยนแปลงบางอย่างกับสคริปต์ของคุณเพื่อรับมือกับอักขระพิเศษในชื่อไฟล์ (ช่องว่างเครื่องหมายขีดกลางและจุดเริ่มต้น\[?*) อ่านแนะนำ: ไม่แยกผลลัพธ์ของคำสั่ง ls , $ VAR VS $ {} VAR และจะพูดหรือไม่ที่จะอ้าง โปรดทราบว่าฉันยังไม่ได้ทดสอบสคริปต์ผลลัพธ์ หากคุณไม่เข้าใจการเปลี่ยนแปลงของฉันโปรดถาม
Gilles 'หยุดความชั่วร้าย'

@Gilles: ฉันได้อ่านมากมายตั้งแต่ปี 2008 ;-) การเปลี่ยนแปลงเพื่อให้สคริปต์ทั่วไปดีขึ้น (ฉันไม่ชอบการแนะนำ[เมื่อเทียบกับtestแม้ว่า) ...
MattBianco

คุณควรเป็นตัวพิมพ์เล็กของตัวแปรเหล่านั้นส่วนใหญ่ ตามแบบแผนเราใช้ประโยชน์จากตัวแปรสภาพแวดล้อม (PAGER, EDITOR, SHELL, ... ) และตัวแปรเชลล์ภายใน ชื่อตัวแปรอื่น ๆ ทั้งหมดควรมีตัวอักษรพิมพ์เล็กอย่างน้อยหนึ่งตัว อนุสัญญานี้หลีกเลี่ยงการแก้ไขตัวแปรสภาพแวดล้อมและภายในโดยไม่ตั้งใจ
Chris Down

2

ฉันเคยเขียนสคริปต์เพื่อแก้ปัญหาที่คล้ายกัน - ฉันเรียกมันว่า "แจกจ่าย" (คุณสามารถอ่านรหัสหลักของสคริปต์หรือไฟล์ที่มีข้อความช่วยเหลือหรือดาวน์โหลดเป็นแพคเกจ ); จากคำอธิบาย :

แจกจ่าย - แจกจ่ายคอลเลกชันของแพ็คเกจบนซีดีหลาย ๆ แผ่น (โดยเฉพาะอย่างยิ่งเหมาะสำหรับใช้กับ APT ในอนาคต)

คำอธิบาย: โปรแกรม `แจกจ่าย 'ทำให้การทำงานที่เกี่ยวข้องกับการสร้างชุดซีดีสำหรับการแจกจ่ายชุดรวบรวมทำได้ง่ายขึ้น งานรวมถึง: การจัดวางระบบไฟล์ซีดี (แบ่งบรรจุภัณฑ์จำนวนมากออกเป็นหลายแผ่น ฯลฯ ) การเตรียมคอลเลกชันสำหรับใช้โดย APT (การทำดัชนี) การสร้างอิมเมจ ISO และการบันทึกแผ่นดิสก์

การอัปเดตเป็นระยะเพื่อรวบรวมชุดเริ่มต้นสามารถออกได้ด้วยความช่วยเหลือของ `แจกจ่าย '

มันทำกระบวนการทั้งหมดในหลายขั้นตอน: ในขั้นตอนเดียวมันจะสร้าง "เลย์เอาต์" ของ furure disk โดยใช้ symlink ไปยังไฟล์ดั้งเดิม - เพื่อให้คุณสามารถแทรกแซงและเปลี่ยนโครงสร้างดิสก์ในอนาคต

รายละเอียดเกี่ยวกับการใช้งานสามารถอ่านได้ในข้อความช่วยเหลือที่พิมพ์โดยสคริปต์ (หรือโดยดูที่ซอร์สโค้ด)

มันถูกเขียนขึ้นโดยคำนึงถึงกรณีการใช้งานที่ซับซ้อนมากขึ้น (การออกอัพเดตเป็น "diff" - ชุดของไฟล์ใหม่ที่เพิ่ม - ไปยังคอลเลกชันของไฟล์ที่บันทึกไว้เดิม) ดังนั้นจึงรวมขั้นตอนแรกไว้หนึ่งชุดคือ "สถานะปัจจุบันของการรวบรวมไฟล์ (สำหรับความเรียบง่ายทำได้โดยการทำซ้ำการรวบรวมไฟล์ดั้งเดิมโดยใช้ symlink ในสถานที่ทำงานพิเศษสำหรับการบันทึกสถานะของการรวบรวมจากนั้นบางเวลาในอนาคต จะสามารถสร้างความแตกต่างระหว่างสถานะปัจจุบันในอนาคตของการเก็บรวบรวมไฟล์และสถานะที่บันทึกไว้นี้) ดังนั้นแม้ว่าคุณอาจไม่ต้องการฟีเจอร์นี้ แต่คุณไม่สามารถข้ามขั้นตอนแรกได้นั่นคือ AFAIR

นอกจากนี้ฉันไม่แน่ใจว่าตอนนี้ (ฉันเขียนเมื่อไม่กี่ปีที่ผ่านมา) ไม่ว่าจะใช้ต้นไม้ที่ซับซ้อนหรือไม่หรือควรแบ่งไดเรกทอรีไฟล์ (ระดับเดียว) ธรรมดา (โปรดดูข้อความช่วยเหลือหรือซอร์สโค้ดเพื่อให้แน่ใจว่าฉันจะตรวจสอบสิ่งนี้ด้วยในภายหลังเมื่อฉันมีเวลา)

สิ่งที่เกี่ยวข้องกับ APT นั้นเป็นตัวเลือกดังนั้นอย่าสนใจว่าจะสามารถจัดทำชุดรวมของชุดข้อมูลที่ APT จะใช้หากคุณไม่ต้องการสิ่งนี้

หากคุณสนใจแน่นอนสามารถเขียนมันใหม่ตามความต้องการของคุณหรือแนะนำการปรับปรุง

(โปรดทราบว่าแพคเกจรวมถึงแพทช์ที่มีประโยชน์เพิ่มเติมที่ไม่ได้ใช้ในรายการรหัสที่นำเสนอที่ repo Git ลิงค์ข้างต้น!)


ฉันได้นำเสนอ - ในสิ่งอื่น ๆ - รหัสที่ตัดตอนมาจากdistributeนั้นแก้งานสำคัญที่ถามเกี่ยวกับที่นี่
imz - Ivan Zakharyaschev

2

เราไม่ควรลืมว่าสาระสำคัญของงานนั้นค่อนข้างง่าย ใส่ในการสอนเกี่ยวกับ Haskell (ซึ่งเขียนรอบการทำงานผ่านการแก้ปัญหาสำหรับงานนี้การปรับปรุงทีละน้อย)

ตอนนี้ลองคิดดูสักครู่ว่าโปรแกรมของเราจะทำงานอย่างไรและแสดงเป็น pseudocode:

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

ฟังดูสมเหตุสมผลหรือไม่ ฉันคิดอย่างนั้น

มาทำให้ชีวิตของเราง่ายขึ้นเล็กน้อยและสมมติว่าตอนนี้เราจะคำนวณขนาดไดเรกทอรีบางแห่งนอกโปรแกรมของเรา (เช่นด้วย " du -sb *") และอ่านข้อมูลนี้จาก stdin

(จากHitchhikers แนะนำสู่ Haskell ตอนที่ 1 )

(นอกจากนี้ในคำถามของคุณคุณต้องการที่จะสามารถปรับแต่ง (แก้ไข) รูปแบบดิสก์ที่เกิดจากนั้นใช้เครื่องมือในการเผาไหม้พวกเขา)

คุณสามารถนำกลับมาใช้ใหม่ (ดัดแปลงและนำกลับมาใช้ใหม่) ได้อย่างง่าย ๆ จากโปรแกรม Haskell เพื่อการแบ่งไฟล์ของคุณ

แต่น่าเสียดายที่ในเครื่องมือที่ผมเคยกล่าวถึงที่นี่ในคำตอบอื่น , ความเรียบง่ายของงานแยกที่สำคัญไม่ตรงกับความซับซ้อนและ bloatedness ของอินเตอร์เฟซผู้ใช้(เพราะมันถูกเขียนขึ้นเพื่อรวมงานหลายแห่งแม้จะดำเนินการในขั้นตอน แต่ยังรวมกันไม่ได้ในวิธีที่สะอาดที่สุดที่ฉันสามารถคิดได้ในขณะนี้)distributedistribute

เพื่อช่วยให้คุณใช้ประโยชน์จากรหัสของมันนี่คือข้อความที่ตัดตอนมาจาก bash-code ของ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ฟังก์ชั่นเตรียมเค้าโครงของดิสก์ในอนาคตเป็นแผนผังซึ่งใบไม้เป็น symlink ไปยังไฟล์จริง ดังนั้นจึงเป็นไปตามความต้องการของคุณที่คุณควรจะสามารถแก้ไขเลย์เอาต์ก่อนที่จะเขียน mkisofsยูทิลิตี้มีตัวเลือกที่จะปฏิบัติตาม symlinks ซึ่งเป็นลูกจ้างแน่นอนในรหัสของฉันmkisoฟังก์ชั่น

สคริปต์ที่นำเสนอ (ซึ่งคุณสามารถนำไปใช้และเขียนซ้ำตามความต้องการของคุณ!) ตามความคิดที่ง่ายที่สุด: เพื่อรวมขนาดของไฟล์ (หรือแม่นยำยิ่งขึ้นแพ็คเกจในกรณีของdistribute) เพียงในลำดับที่พวกเขาอยู่ในรายการอย่า ไม่ต้องจัดเรียงใหม่

"Hitchhikers guide to Haskell" ให้ความสำคัญกับปัญหาการปรับให้เหมาะสมที่สุดและแนะนำตัวแปรของโปรแกรมที่จะพยายามจัดเรียงไฟล์ใหม่อย่างชาญฉลาดเพื่อให้พวกเขาสามารถใส่ดิสก์ได้ดีขึ้น

เพียงพอเบื้องต้นแล้ว ไปเก็บซีดีกันบ้าง

ในขณะที่คุณอาจได้รับการยอมรับปัญหาของเราเป็นคลาสสิก มันถูกเรียกว่า"ปัญหาเป้" ( googleถ้าคุณไม่ทราบว่ามันคืออะไรมีมากกว่า 100,000 ลิงก์)

เริ่มจากทางออกโลภ ...

(อ่านเพิ่มเติมในบทที่ 3ขึ้นไป)

เครื่องมืออัจฉริยะอื่น ๆ

ฉันได้รับการบอกด้วยว่า Debian ใช้เครื่องมือในการทำซีดี distro ที่ฉลาดกว่าdistributeชุด wrt ของฉัน: ผลลัพธ์ของมันดีกว่าเพราะมันให้ความสำคัญกับการพึ่งพาระหว่างแพ็กเกจและจะพยายามรวบรวมชุดที่ได้รับ ดิสก์แรกที่ปิดอยู่ภายใต้การอ้างอิงคือไม่มีแพ็คเกจจากดิสก์ที่ 1 ควรต้องใช้แพคเกจจากดิสก์อื่น


1

backup2l สามารถทำงานนี้ได้มาก แม้ว่าคุณจะไม่ได้ใช้แพ็คเกจโดยตรง แต่คุณอาจได้รับแนวคิดเกี่ยวกับสคริปต์จากมัน


0

ผู้rarจัดเก็บสามารถสั่งให้แยกไฟล์เก็บถาวรที่สร้างขึ้นเป็นชิ้นขนาดที่ระบุด้วย-vsizeแฟล็กโดยอัตโนมัติ

การเก็บทรีไดเรกทอรีนั้นมีชื่อfooอยู่ในกลุ่มข้อมูลขนาด 500 เมกะไบต์ที่คุณระบุ
rar a backup.rar -v500m foo/


2
ทำไมถึงเป็น rar tar (+ bz2) + split เป็นวิธีการดั้งเดิมมากขึ้นสำหรับ * ระวัง
rvs

"ต้นไม้ที่มีขนาดกัด" นั้นฟังดูไม่ค่อยดีrarเว้นแต่คุณจะแกะ "ส่วน" แต่ละอันอีกครั้งลงในไดเรกทอรีของตัวเองซึ่งแน่นอนว่าจะไม่ทำงานเนื่องจากชิ้นส่วนไม่ได้รับการออกแบบอย่างนั้นและไม่แยกขอบเขตของไฟล์
MattBianco

1
หากพูดถึงเครื่องมือที่ให้ผลลัพธ์ที่เหมือนtar+ splitแล้วก็มีความน่ากลัวเช่นกัน นี่คือหมายเหตุเกี่ยวกับคุณสมบัติที่เกี่ยวข้อง: "(SLices) มันถูกออกแบบมาเพื่อให้สามารถแยกการเก็บถาวรผ่านสื่อที่ถอดได้หลายชนิดไม่ว่าหมายเลขของพวกเขาคืออะไรและขนาดใดก็ตาม" เทียบกับtar+ splitฉันคิดว่ามันช่วยให้เข้าถึงวิธีการเข้าถึงไฟล์ที่เก็บถาวรได้ง่ายขึ้น (BTW มันยังมีคุณสมบัติคล้ายdistribute: "การสำรองข้อมูลที่แตกต่างกัน" & "DIRECTORY TREE SNAPSHOT" แต่อาจไม่เหมือนว่าผลลัพธ์จะเป็นรูปแบบพิเศษไม่ใช่ ISO กับต้นไม้ dir)
imz - Ivan Zakharyaschev
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.