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 distribute
alat 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 eatFiles
fungsi 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 mkisofs
utilitas memiliki opsi untuk mengikuti symlink, yang memang digunakan dalam kode saya mkiso
fungsi .
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 distribute
koleksi 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).