GNU/Linux >> Znalost Linux >  >> Linux

jak vytvořit multi tar archivy pro obrovskou složku

Napsal jsem tento bash skript, abych to udělal. V podstatě tvoří pole obsahující názvy souborů, které se mají vložit do každého tar, a pak začíná tar souběžně se všemi .Možná to není nejúčinnější způsob, ale udělá práci tak, jak chcete. Mohu očekávat, že bude spotřebovávat velké množství paměti.

Budete muset upravit možnosti na začátku skriptu. Můžete také změnit možnosti tar cvjf na posledním řádku (jako je odstranění podrobného výstupu v pro výkon nebo změnu komprese jz , atd...).

Skript

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

Vysvětlení

Nejprve jsou všechny názvy souborů, které odpovídají vybranému vzoru, uloženy v poli files . Dále smyčka for toto pole rozřízne a vytvoří z řezů řetězce. Počet řezů se rovná počtu požadovaných tarballů. Výsledné řetězce jsou uloženy v poli tar_files . Smyčka for také přidá název výsledného tarballu na začátek každého řetězce. Prvky tar_files mít následující podobu (za předpokladu 5 souborů/tarball):

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

Poslední řádek skriptu, xargs se používá ke spuštění více tar procesy (až do maximálního zadaného počtu), kde každý zpracuje jeden prvek ze tar_files pole paralelně.

Test

Seznam souborů:

$ls

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

Vygenerované tarbally:$ls /tmp/tar*tar0.tar.bz2 tar1.tar.bz2 tar2.tar.bz2 tar3.tar.bz2


Tady je další skript. Můžete si vybrat, zda chcete přesně jeden milion souborů na segment, nebo přesně 30 segmentů. V tomto skriptu jsem použil první verzi, ale split klíčové slovo umožňuje obě volby.

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

Existuje řada jemností, které lze na tento skript použít. Použití /tmp/chunk. protože předpona seznamu souborů by měla být pravděpodobně vytlačena do konstantní deklarace a kód by ve skutečnosti neměl předpokládat, že může odstranit cokoli odpovídající /tmp/chunk.* , ale nechal jsem to tak, spíše jako důkaz konceptu než jako vybroušený nástroj. Pokud bych používal toto, použil bych mktemp pro vytvoření dočasného adresáře pro uložení seznamů souborů.


Tento dělá přesně to, co bylo požadováno:

#!/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 (v bash) lze také použít k provedení funkce zpětného volání, takže by mohla být potenciálně přepsána, aby se podobala:

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

GNU parallel by se dalo využít k něčemu podobnému (netestováno; nemám parallel nainstalovaný tam, kde jsem, takže to otočím):

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

Protože to není otestováno, můžete přidat --dry-run arg, abyste viděli, co to vlastně udělá. Tenhle se mi líbí nejvíc, ale ne každý má parallel nainstalováno. -j4 umožňuje používat 4 úlohy najednou, -d '\0' v kombinaci s find 's -print0 umožňuje ignorovat speciální znaky v názvu souboru (mezery atd.). Zbytek by měl být samozřejmý.

Něco podobného by se dalo udělat s parallel ale nelíbí se mi to, protože generuje náhodné názvy souborů:

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

[zatím?] nevím o způsobu, jak vytvořit sekvenční názvy souborů.

xargs lze také použít, ale na rozdíl od parallel neexistuje žádný přímočarý způsob, jak vygenerovat výstupní soubor, takže byste nakonec udělali něco hloupého/háklivého, jako je toto:

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 řekli, že nechtějí použít split... Myslel jsem, že to vypadá divně jako cat v pohodě se k nim znovu připojí; tím vznikne dehet a rozdělí se na 3gb části:

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

... a tím je odtartujete do aktuálního adresáře:

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

Linux
  1. Příklady cpio pro Linux:Jak vytvořit a extrahovat archivy cpio (a archivy tar)

  2. Jak vyloučím absolutní cesty pro tar?

  3. Jak zakázat vytváření složky .Trash-1000?

  1. Jak zabalit aplikace Python pro Linux

  2. Jak vytvořit sdílený adresář pro všechny uživatele v Linuxu

  3. Vytvořit archiv Tar z adresáře, s výjimkou skrytých souborů?

  1. Jak vytvořit pem pro váš stávající SSL

  2. Jak mohu vytvořit soubor v každé složce?

  3. Jak mohu vytvořit vícedílný soubor tar v Linuxu?