GNU/Linux >> Belajar Linux >  >> Linux

cara membuat arsip multi tar untuk folder besar

Saya menulis skrip bash ini untuk melakukannya. Ini pada dasarnya membentuk larik yang berisi nama file untuk masuk ke setiap tar, lalu memulai tar secara paralel dengan semuanya .Ini mungkin bukan cara yang paling efisien, tetapi ini akan menyelesaikan pekerjaan seperti yang Anda inginkan.Namun, saya dapat mengharapkannya menghabiskan banyak memori.

Anda perlu menyesuaikan opsi di awal skrip. Anda mungkin juga ingin mengubah opsi tar cvjf di baris terakhir (seperti menghapus keluaran verbose v untuk kinerja atau mengubah kompresi j ke z , dll ...).

Skrip

#!/bin/bash

# User configuratoin
#===================
files=(*.log)           # Set the file pattern to be used, e.g. (*.txt) or (*)
num_files_per_tar=5 # Number of files per tar
num_procs=4         # Number of tar processes to start
tar_file_dir='/tmp' # Tar files dir
tar_file_name_prefix='tar' # prefix for tar file names
tar_file_name="$tar_file_dir/$tar_file_name_prefix"

# Main algorithm
#===============
num_tars=$((${#files[@]}/num_files_per_tar))  # the number of tar files to create
tar_files=()  # will hold the names of files for each tar

tar_start=0 # gets update where each tar starts
# Loop over the files adding their names to be tared
for i in `seq 0 $((num_tars-1))`
do
  tar_files[$i]="$tar_file_name$i.tar.bz2 ${files[@]:tar_start:num_files_per_tar}"
  tar_start=$((tar_start+num_files_per_tar))
done

# Start tar in parallel for each of the strings we just constructed
printf '%s\n' "${tar_files[@]}" | xargs -n$((num_files_per_tar+1)) -P$num_procs tar cjvf

Penjelasan

Pertama, semua nama file yang cocok dengan pola yang dipilih disimpan dalam larik files . Selanjutnya, for loop mengiris array ini dan membentuk string dari irisan tersebut. Jumlah irisan sama dengan jumlah tarbal yang diinginkan. String yang dihasilkan disimpan dalam larik tar_files . Perulangan for juga menambahkan nama tarball yang dihasilkan ke awal setiap string. Elemen tar_files ambil formulir berikut (dengan asumsi 5 file/tarball):

tar_files[0]="tar0.tar.bz2  file1 file2 file3 file4 file5"
tar_files[1]="tar1.tar.bz2  file6 file7 file8 file9 file10"
...

Baris terakhir skrip, xargs digunakan untuk memulai beberapa tar memproses (hingga jumlah maksimum yang ditentukan) di mana masing-masing akan memproses satu elemen tar_files array secara paralel.

Uji

Daftar file:

$ls

a      c      e      g      i      k      m      n      p      r      t
b      d      f      h      j      l      o      q      s

Tarball yang Dihasilkan:$ls /tmp/tar*tar0.tar.bz2 tar1.tar.bz2 tar2.tar.bz2 tar3.tar.bz2


Ini skrip lain. Anda dapat memilih apakah Anda menginginkan tepat satu juta file per segmen, atau tepatnya 30 segmen. Saya menggunakan yang pertama dalam skrip ini, tetapi split kata kunci memungkinkan salah satu pilihan.

#!/bin/bash
#
DIR="$1"        # The source of the millions of files
TARDEST="$2"    # Where the tarballs should be placed

# Create the million-file segments
rm -f /tmp/chunk.*
find "$DIR" -type f | split -l 1000000 - /tmp/chunk.

# Create corresponding tarballs
for CHUNK in $(cd /tmp && echo chunk.*)
do
    test -f "$CHUNK" || continue

    echo "Creating tarball for chunk '$CHUNK'" >&2
    tar cTf "/tmp/$CHUNK" "$TARDEST/$CHUNK.tar"
    rm -f "/tmp/$CHUNK"
done

Ada sejumlah kebaikan yang dapat diterapkan pada skrip ini. Penggunaan /tmp/chunk. karena awalan daftar file mungkin harus didorong keluar ke deklarasi konstan, dan kode tidak boleh benar-benar menganggap itu dapat menghapus apa pun yang cocok dengan /tmp/chunk.* , tapi saya membiarkannya seperti ini sebagai bukti konsep daripada utilitas yang dipoles. Jika saya menggunakan ini, saya akan menggunakan mktemp untuk membuat direktori sementara untuk menyimpan daftar file.


Yang ini melakukan persis seperti yang diminta:

#!/bin/bash
ctr=0;
# Read 1M lines, strip newline chars, put the results into an array named "asdf"
while readarray -n 1000000 -t asdf; do
  ctr=$((${ctr}+1));
# "${asdf[@]}" expands each entry in the array such that any special characters in
# the filename won't cause problems
  tar czf /destination/path/asdf.${ctr}.tgz "${asdf[@]}";
# If you don't want compression, use this instead:
  #tar cf /destination/path/asdf.${ctr}.tar "${asdf[@]}";
# this is the canonical way to generate output
# for consumption by read/readarray in bash
done <(find /source/path -not -type d);

readarray (dalam bash) juga dapat digunakan untuk menjalankan fungsi panggilan balik, sehingga berpotensi ditulis ulang agar menyerupai:

function something() {...}
find /source/path -not -type d \
  | readarray -n 1000000 -t -C something asdf

GNU parallel dapat dimanfaatkan untuk melakukan hal serupa (belum diuji; saya tidak punya parallel diinstal di tempat saya berada jadi saya akan melakukannya):

find /source/path -not -type d -print0 \
  | parallel -j4 -d '\0' -N1000000 tar czf '/destination/path/thing_backup.{#}.tgz'

Karena itu belum teruji, Anda dapat menambahkan --dry-run arg untuk melihat apa yang sebenarnya akan dilakukannya. Saya paling suka yang ini, tetapi tidak semua orang memiliki parallel diinstal. -j4 membuatnya menggunakan 4 pekerjaan sekaligus, -d '\0' dikombinasikan dengan find -print0 membuatnya mengabaikan karakter khusus dalam nama file (spasi putih, dll). Sisanya harus cukup jelas.

Hal serupa dapat dilakukan dengan parallel tapi saya tidak suka karena menghasilkan nama file acak:

find /source/path -not -type d -print0 \
  | parallel -j4 -d '\0' -N1000000 --tmpdir /destination/path --files tar cz

Saya [belum?] tahu cara membuatnya menghasilkan nama file berurutan.

xargs juga dapat digunakan, tetapi tidak seperti parallel tidak ada cara langsung untuk menghasilkan nama file keluaran sehingga Anda akhirnya melakukan sesuatu yang bodoh/hacky seperti ini:

find /source/path -not -type d -print0 \
  | xargs -P 4 -0 -L 1000000 bash -euc 'tar czf $(mktemp --suffix=".tgz" /destination/path/backup_XXX) "[email protected]"'

OP mengatakan mereka tidak ingin menggunakan split ... Saya pikir itu aneh seperti cat akan bergabung kembali dengan mereka dengan baik; ini menghasilkan tar dan membaginya menjadi potongan 3gb:

tar c /source/path | split -b $((3*1024*1024*1024)) - /destination/path/thing.tar.

... dan ini menghapus tar mereka ke direktori saat ini:

cat $(\ls -1 /destination/path/thing.tar.* | sort) | tar x

Linux
  1. Cara Membuat gambar Windows untuk OpenStack

  2. Buat Arsip Tar Dari Direktori, Kecuali Untuk File Tersembunyi?

  3. Cara Membuat pem Untuk SSL Anda yang Ada

  1. Cara mengemas aplikasi Python untuk Linux

  2. Contoh cpio Linux:Cara Membuat dan Mengekstrak Arsip cpio (dan arsip tar)

  3. Bagaimana cara mengecualikan jalur absolut untuk tar?

  1. Cara Membuat Direktori Bersama untuk Semua Pengguna di Linux

  2. Bagaimana saya bisa membuat file di setiap folder?

  3. Bagaimana saya bisa membuat file tar multipart di Linux?