Membagi pohon direktori besar menjadi potongan ukuran tertentu?

11

Saya memiliki pohon direktori yang ingin saya buat cadangannya ke cakram optik. Sayangnya, ukurannya melebihi ukuran disk apa pun (sekitar 60GB). Saya mencari skrip yang akan membagi pohon ini menjadi potongan-potongan berukuran tepat dengan tautan keras atau yang lainnya (membiarkan dokumen asli tidak tersentuh). Saya kemudian bisa memberi makan pohon ukuran gigitan ini ke dalam proses pencadangan (tambahkan PAR2 redundansi, dll.).

Ini bukan skrip mewah, tapi sepertinya sudah dilakukan. Saran?

(Mencentang dan menulis dalam satu langkah adalah jalan karena saya ingin melakukan lebih banyak hal sebelum file dibakar.)

Reid
sumber
Sudahkah Anda mempertimbangkan untuk menjadi penulis bluray?
bsd
2
Media DVD tidak dapat diandalkan ... Saya akan merekomendasikan drive eksternal, cadangan online seperti Carbonite, atau jika membakar media, gunakan par2perlindungan.
Aaron D. Marasco

Jawaban:

7

Ada aplikasi yang dirancang untuk ini: dirsplit

Biasanya tinggal cdrkitatau dirsplitpaket.

Itu dapat membuat folder yang siap digunakan dengan tautan untuk dengan mudah membuat DVD dengan K3b atau perangkat lunak GUI lainnya

Hubert Kario
sumber
Ini bekerja dengan sangat baik. Di Ubuntu saya menemukannya di genisoimagepaket.
memotret
2

Saya pernah membuat naskah jelek untuk tujuan yang sama. Itu hanya kludge, tetapi ketika saya menulisnya, saya tidak peduli dengan waktu eksekusi atau kecantikan. Saya yakin ada lebih banyak versi "produk" dari konsep yang sama, tetapi jika Anda ingin mendapatkan beberapa ide atau sesuatu untuk memulai peretasan, begini (melakukannya pada tahun 2008, jadi gunakan dengan risiko Anda sendiri!): - )

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

Saya pikir saya memiliki hasil yang dibagikan melalui samba ke host windows yang membakar disk dari itu. Jika Anda menggunakan hal di atas yang tidak diubah, Anda mungkin ingin menggunakan mkisofsatau pengarsip lain yang menyelesaikan symlink.

MattBianco
sumber
Saya telah membuat beberapa perubahan pada skrip Anda untuk mengatasi karakter khusus dalam nama file (spasi putih, tanda hubung awal dan titik, \[?*). Bacaan yang disarankan: jangan parsing output dari ls , $ VAR vs $ {VAR} dan mengutip atau tidak mengutip . Perhatikan bahwa saya belum menguji skrip yang dihasilkan. Jika Anda tidak mengerti satu perubahan saya, jangan ragu untuk bertanya.
Gilles 'SO- stop being evil'
@Gilles: Saya sudah banyak membaca sejak 2008 ;-) Perubahan untuk membuat skrip lebih umum menjadi baik. (Saya tidak suka pengenalan yang [bertentangan dengan test) ...
MattBianco
Anda harus mengurangi sebagian besar variabel tersebut. Secara konvensi, kami mengkapitalkan variabel lingkungan (PAGER, EDITOR, SHELL, ...) dan variabel shell internal. Semua nama variabel lainnya harus mengandung setidaknya satu huruf kecil. Konvensi ini menghindari override variabel lingkungan dan internal yang tidak sengaja.
Chris Down
2

Saya pernah menulis skrip untuk memecahkan masalah yang sama - saya menyebutnya "sebarkan" (Anda dapat membaca kode utama skrip atau file dengan pesan bantuan , atau mengunduhnya sebagai paket ); dari deskripsinya :

mendistribusikan - Mendistribusikan koleksi paket pada beberapa CD (sangat baik untuk digunakan di masa depan dengan APT)

Deskripsi: Program `distribusikan 'membuat melakukan tugas-tugas yang terkait dengan membuat set CD untuk distribusi kumpulan paket lebih mudah. Tugas-tugas tersebut meliputi: menata sistem file CD (memecah sejumlah besar paket menjadi beberapa disk, dll.), Menyiapkan koleksi untuk digunakan oleh APT (pengindeksan), membuat gambar ISO dan merekam disk.

Pembaruan berkala untuk koleksi yang awalnya didistribusikan dapat dikeluarkan dengan bantuan `mendistribusikan '.

Itu melakukan seluruh proses dalam beberapa tahap: pada satu tahap, ia menciptakan "layout" furure disk dengan menggunakan symlink ke file asli - sehingga Anda dapat melakukan intervensi dan mengubah pohon disk masa depan.

Rincian tentang penggunaannya dapat dibaca dalam pesan bantuan yang dicetak oleh skrip (atau dengan melihat ke kode sumber).

Itu ditulis dengan kasus penggunaan yang lebih rumit dalam pikiran (mengeluarkan pembaruan sebagai "diff" - kumpulan file baru yang ditambahkan - ke kumpulan file yang awalnya direkam), sehingga mencakup satu tahap awal tambahan, yaitu, "memperbaiki "Keadaan saat pengumpulan file (untuk kesederhanaan, ia melakukan ini dengan mereplikasi koleksi file asli dengan menggunakan symlink, di tempat kerja khusus untuk menyimpan keadaan koleksi; kemudian, beberapa waktu di masa depan, itu akan dapat membuat perbedaan antara keadaan saat ini dari koleksi file dan keadaan tersimpan ini). Jadi, meskipun Anda mungkin tidak membutuhkan fitur ini, Anda tidak dapat melewati tahap awal ini, AFAIR.

Juga, saya tidak yakin sekarang (saya menulisnya beberapa tahun yang lalu) apakah itu memperlakukan pohon yang kompleks dengan baik, atau seharusnya hanya membagi direktori file (satu level) biasa. (Silakan melihat ke dalam pesan bantuan atau kode sumber untuk memastikan; Saya akan mencari ini juga, sedikit kemudian, ketika saya akan punya waktu.)

Hal-hal yang berhubungan dengan APT adalah opsional, jadi jangan perhatikan bahwa hal itu dapat menyiapkan koleksi paket untuk digunakan oleh APT jika Anda tidak membutuhkannya.

Jika Anda tertarik, tentu saja, silakan menulis ulang sesuai kebutuhan Anda atau menyarankan peningkatan.

(Harap perhatikan bahwa paket menyertakan tambalan berguna tambahan yang tidak diterapkan dalam daftar kode yang disajikan di repo Git yang tertaut di atas!)

imz - Ivan Zakharyaschev
sumber
Saya telah mempresentasikan - di antara hal-hal lain - kutipan kode distributeyang menyelesaikan tugas penting yang ditanyakan di sini.
imz - Ivan Zakharyaschev
2

Kita tidak boleh lupa bahwa esensi dari tugas itu memang cukup sederhana; seperti yang dimasukkan dalam tutorial tentang Haskell (yang ditulis sekitar penyelesaian solusi untuk tugas ini, secara bertahap disempurnakan)

Sekarang mari kita berpikir sejenak tentang bagaimana program kami akan beroperasi dan mengekspresikannya dalam pseudocode:

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

Kedengarannya masuk akal? Saya pikir juga begitu.

Mari kita sederhanakan sedikit kehidupan kita dan berasumsi untuk sekarang bahwa kita akan menghitung ukuran direktori di suatu tempat di luar program kita (misalnya, dengan " du -sb *") dan membaca informasi ini dari stdin.

(dari panduan Hitchhikers ke Haskell, Bab 1 )

(Tambahan lagi, dalam pertanyaan Anda, Anda ingin dapat mengubah (mengedit) tata letak disk yang dihasilkan, dan kemudian menggunakan alat untuk membakarnya.)

Anda dapat menggunakan kembali (mengadaptasi dan menggunakan kembali) varian sederhana dari program dari tutorial Haskell untuk memisahkan koleksi file Anda.

Sayangnya, di dalam distributealat yang saya sebutkan di sini dalam jawaban lain , kesederhanaan tugas membelah penting tidak diimbangi dengan kompleksitas dan kembung dari antarmuka pengguna distribute(karena ditulis untuk menggabungkan beberapa tugas, walaupun dilakukan secara bertahap, tetapi masih dikombinasikan tidak dengan cara terbersih yang bisa saya pikirkan sekarang).

Untuk membantu Anda menggunakan kodenya, berikut adalah kutipan dari bash-code distribute(pada baris 380 ) yang berfungsi untuk melakukan tugas "esensial" ini yaitu memecah kumpulan file:

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

( baca selengkapnya setelah baris 454 )

Perhatikan bahwa eatFilesfungsi menyiapkan tata letak disk masa depan sebagai pohon di mana daunnya adalah symlink ke file nyata. Jadi, ini memenuhi persyaratan Anda bahwa Anda harus dapat mengedit tata letak sebelum membakar. The mkisofsutilitas memiliki opsi untuk mengikuti symlink, yang memang digunakan dalam kode saya mkisofungsi .

Skrip yang disajikan (yang dapat Anda ambil dan tulis ulang sesuai kebutuhan Anda, tentu saja!) Mengikuti ide yang paling sederhana: untuk menjumlahkan ukuran file (atau, lebih tepatnya, paket dalam hal distribute) hanya dalam urutan yang terdaftar, jangan dapat melakukan pengaturan ulang.

"Hitchhikers guide to Haskell" menangani masalah pengoptimalan dengan lebih serius dan menyarankan varian program yang akan mencoba mengatur ulang file dengan cerdas, agar mereka lebih pas di disk (dan membutuhkan lebih sedikit disk):

Pendahuluan sudah cukup. ayo kita berkemas beberapa CD.

Seperti yang mungkin sudah Anda ketahui, masalah kami adalah masalah klasik. Ini disebut "masalah ransel" ( google it up , jika Anda belum tahu apa itu. Ada lebih dari 100.000 tautan).

mari kita mulai dari solusi serakah ...

(baca lebih lanjut di Bab 3 dan lebih lanjut.)

Alat pintar lainnya

Saya telah diberitahu juga bahwa Debian menggunakan alat untuk membuat CD distro-nya yang lebih pintar daripada distributekoleksi paket wrt saya : hasilnya lebih baik karena peduli dengan ketergantungan antar paket dan akan mencoba membuat kumpulan paket yang berjalan disk pertama ditutup di bawah dependensi, yaitu, tidak ada paket dari disk ke-1 yang memerlukan paket dari disk lain (atau setidaknya, menurut saya, jumlah dependensi seperti itu harus diminimalkan).

imz - Ivan Zakharyaschev
sumber
1

backup2l dapat melakukan banyak pekerjaan ini. Bahkan jika Anda tidak menggunakan paket secara langsung, Anda mungkin mendapatkan beberapa ide skrip darinya.

Randy Coulman
sumber
0

The rarPengarsip dapat diinstruksikan untuk secara otomatis membagi arsip itu menciptakan menjadi potongan dari ukuran tertentu dengan -vsizebendera.

Pengarsipan pohon direktori yang dinamai foomenjadi potongan, katakanlah, 500 megabyte masing-masing yang Anda tentukan
rar a backup.rar -v500m foo/

Shadur
sumber
2
Lalu mengapa rar? tar (+ bz2) + split adalah pendekatan yang lebih asli untuk * nix.
rvs
"pohon ukuran gigitan" tidak terdengar seperti itu rar, kecuali jika Anda membongkar setiap "bagian" lagi ke direktori sendiri, yang tentu saja tidak akan berfungsi, karena bagian-bagiannya tidak dirancang seperti itu, dan tidak terpecah pada batas-batas file.
MattBianco
1
Jika berbicara tentang alat yang memberikan hasil seperti tar+ split, maka ada juga dar ; inilah catatan tentang fitur yang relevan: "(SLICES) dirancang untuk dapat membagi arsip menjadi beberapa media yang dapat dilepas berapa pun jumlahnya dan berapa pun ukurannya". Dibandingkan dengan tar+ split, saya berasumsi, ini memungkinkan beberapa cara lebih mudah untuk mengakses file yang diarsipkan. (BTW, ia juga memiliki fitur yang menyerupai distribute: "CADANGAN DIFERENSIAL" & "DIRECTORY TREE SNAPSHOT", tetapi orang mungkin tidak suka bahwa hasilnya adalah format khusus, bukan ISO dengan pohon dir.)
imz - Ivan Zakharyaschev