繰り返しファイル圧縮

繰り返しファイル圧縮

77K PDF(サイズ約500 GB)を含むフォルダがあります。簡単にアップロードして同僚と共有できるように、各ファイルに1000個のPDFを含む77個の圧縮ファイルに圧縮したいと思います。 Bashでforループを作成し、そこでzipコマンドを使用する方法がわかりませんが、いくつかの例を見ました。これ質問。誰でも私を助けることができますか?

ファイル名は次のとおりです。

FinalRoll_MR_ACNo_@PartNo_%%.pdf

@ と %% は数値です。最初の1000個のファイルをarchive_1.tar.gzのようなファイルに圧縮することができれば本当に良いと思います!ファイルの順番をアルファベット順に保つことができればもっといいと思います!

Ubuntuを実行しているAWS ec2インスタンスを使用しています。

よろしくお願いします!

答え1

#!/usr/bin/perl

use strict;
use List::MoreUtils qw(natatime);
use Sort::Naturally;

# specify directory on command line, or default to .
my $dir = shift || '.';

# Find all the PDF files. 
#
# NOTE: you could use perl's `Find::File` module instead of
# readdir() to do a recursive search like `find`.
opendir(DIR, $dir) || die "Can't open $dir: $!\n";
my @pdfs = nsort grep { /\.pdf$/i && -f "$dir/$_" } readdir(DIR);
closedir(DIR);

my $size=1000;

my $i=1;
my $iter = natatime $size, @pdfs;
while( my @tmp = $iter->() ){
  my $tarfile="archive_" . sprintf('%02i',$i++) . ".tar.gz";
  #print join(" ", ('tar','cfz',$tarfile, @tmp)),"\n";
  system('echo','tar','cfz',$tarfile, @tmp);
}

これは、 natatime()PerlList::MoreUtilsライブラリモジュールの(「n-at-a-time」)機能を使用して、一度に1000個のPDFファイルのリストを繰り返します。

また、このSort::Naturallyモジュールを使用してPDFファイル名の自然な順序を実行します。不要な場合や不要な場合は、その項目(および通話nsort中の通貨)を削除してください。my @pdfs = ...

正しいソートのために、tarファイル名にゼロで埋められた2つの数字が含まれています。 99を超えるtarアーカイブを埋めるのに十分なPDFファイルがある場合は、3桁以上に変更してください。

書かれたコードは試運転。実際にPDFファイルのバッチを圧縮するために'echo',関数呼び出しから削除されました。system()

それなしで実行したときに詳細な出力を取得するには、ステートメントのechoコメントを外しますprint。ちなみに、Perlの組み込み機能を使用したり、モジュールを使ってきれいにtime()フォーマットしたり、新起源から数秒後のタイムスタンプを印刷したりするのは簡単ですDate::Format。たとえば、

print join(" ", (time(),'tar','cfz',$tarfile, @tmp)),"\n";

たとえば、vibhu.pl実行可能にするには、別の名前で保存しますchmod +x vibhu.pl。以下はサンプル実行です(「.pdf」ファイルが10個しかないディレクトリ)。

$ touch {1..10}.pdf
$ ./vibhu.pl 
tar cfz archive_01.tar.gz 1.pdf 2.pdf 3.pdf 4.pdf 5.pdf 6.pdf 7.pdf 8.pdf 9.pdf 10.pdf

$size=1000たとえば、に変更すると、$size=3実際にN個のPDFファイルを一度に実行することがわかります。

$ ./vibhu.pl 
tar cfz archive_01.tar.gz 1.pdf 2.pdf 3.pdf
tar cfz archive_02.tar.gz 4.pdf 5.pdf 6.pdf
tar cfz archive_03.tar.gz 7.pdf 8.pdf 9.pdf
tar cfz archive_04.tar.gz 10.pdf

これリスト::追加ユーティリティそして並べ替え::自然モジュールは以下で提供されます。CPAN。展開できるようにすでにパッケージ化されている可能性があります。たとえば、Debianの場合:

sudo apt-get install liblist-moreutils-perl libsort-naturally-perl

答え2

Bashシェルを使用すると、ファイル名を配列に入れて(自然な順序でワイルドカード拡張を使用)、インデックスループで一度に1000個を切り取ることができます。

#!/bin/bash

filenames=( *.pdf )
for((index=1; index <= $(( (${#filenames[@]} / 1000) + 1)); index++))
do
  start=$(( (index-1) * 1000 ))
  tar czf archive"${index}".tar "${filenames[@]:start:999}"
done

このforループは、実行ごとに1000個のファイルをインポートするのに必要な回数だけ実行されます。このstart変数は、配列スライスの開始位置を示します。このtarコマンドは、配列内の1000個のファイルのインデックス付きtarファイルを生成します。ファイル999から始まり、start次の999ファイル(または最後の残りのファイル)で終わります。

答え3

この awk スクリプトを使用してシェルスクリプトを作成できます。圧縮.shを確認して実行してください。

ls *.pdf | awk 'BEGIN {ORS=""; print "#!/bin/sh"; } NR%1000 == 1 {  print "\nzip Archive_" NR ".zip"; } { print " \\\n" $0; }' > compress.sh

答え4

解析してはいけないので、 find と xargs を使う代わりにls

export numfile="$(mktemp)"
echo 0 > "$numfile"

find lots_of_files/ -name '*.pdf' -print0 \
| sort -V -z \
| xargs -0r -L 1000  \
bash -c 'NUM=$(cat "$numfile") ; ((NUM++)); echo "$NUM" > "$numfile"; \
  tar -czf archive_$(printf '%03d' "$NUM" ).tar.gz "$@"' tar_in_batches

rm "$numfile"
unset numfile

前にゼロの付いたアーカイブを取得し、アーカイブのファイルは正しい順序になります。

ファイル名にスペースや改行があっても、このバージョンは中断されません。

関連情報