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
前にゼロの付いたアーカイブを取得し、アーカイブのファイルは正しい順序になります。
ファイル名にスペースや改行があっても、このバージョンは中断されません。