크기가 비슷한 여러 유사한 파일을 여러 개의 아카이브로 tar.gz하는 방법 파일 당 10MB (10000KB)로 제한됩니다 (특히

우분투 16.04에 있습니다.

많은 텍스트 파일 (약 12k)이있는 폴더가 있습니다. 업로드를 허용 .tar.gz한 다음 자동으로 압축 해제 하는 웹 사이트에 파일을 모두 업로드해야 하지만 파일 당 10MB (10000KB)로 제한됩니다 (특히 각 파일의 압축을 해제해야 함). 나는 경우 tar.gz모든 파일 결과 파일은 72메가바이트 약이다.

내가하고 싶은 것은 .tar.gz각각 크기 / 크기 (엄격하게) 10000KB보다 작은 8 개의 파일 을 만드는 것입니다.

또는 위의 모든 파일의 크기가 거의 동일하다고 가정 할 수 있으므로 .tar.gz각각 동일한 파일 양이 많거나 적은 8 개의 파일 을 만들고 싶습니다 .

이 두 가지 작업을 어떻게 수행 할 수 있습니까?

GUI, CLI 또는 스크립팅이 포함 된 솔루션으로 완벽하게 작동합니다. 나는 여기서 속도를 찾지 않고 단지 완료해야합니다.



답변

완전히 패치 워크와 빠르고 대략적인 스케치이지만 3000 개의 파일이있는 디렉토리에서 테스트 한 결과 아래 스크립트는 매우 빠른 작업을 수행했습니다.

#!/usr/bin/env python3
import subprocess
import os
import sys

splitinto = 2

dr = sys.argv[1]
os.chdir(dr)

files = os.listdir(dr)
n_files = len(files)
size = n_files // splitinto

def compress(tar, files):
    command = ["tar", "-zcvf", "tarfile" + str(tar) + ".tar.gz", "-T", "-", "--null"]
    proc = subprocess.Popen(command, stdin=subprocess.PIPE)
    with proc:
        proc.stdin.write(b'\0'.join(map(str.encode, files)))
        proc.stdin.write(b'\0')
    if proc.returncode:
        sys.exit(proc.returncode)

sub = []; tar = 1
for f in files:
    sub.append(f)
    if len(sub) == size:
        compress(tar, sub)
        sub = []; tar += 1

if sub:
    # taking care of left
    compress(tar, sub)

사용하는 방법

  • 빈 파일에 다음과 같이 저장하십시오 compress_split.py
  • 헤드 섹션에서 압축 할 파일 수를 설정하십시오. 실제로, 남은 몇 가지 “왼쪽 오버”를 처리하는 것이 항상 하나 더 있습니다.
  • 파일을 인수로하여 디렉토리에서 실행하십시오.

    python3 /path/tocompress_split.py /directory/with/files/tocompress

번호가 매겨진 .tar.gz파일은 파일이있는 디렉토리와 동일한 디렉토리에 작성됩니다.

설명

스크립트 :

  • 디렉토리의 모든 파일을 나열합니다
  • tar 파일에 경로 정보를 추가하지 못하도록 디렉토리에 cd
  • 파일 목록을 읽고 세트 구분으로 그룹화합니다.
  • 하위 그룹을 번호가 매겨진 파일로 압축

편집하다

MB 단위 크기로 청크 자동 생성

청크의 최대 크기 (MB)를 (두 번째) 인수로 사용하는 것이 더 정교합니다. 아래 스크립트에서 청크는 임계 값에 도달 (통과)하자마자 압축 파일에 기록됩니다.

스크립트는 청크에 의해 트리거되므로 임계 값을 초과하므로 (모든) 파일의 크기가 청크 크기보다 실질적으로 작은 경우에만 작동합니다.

스크립트 :

#!/usr/bin/env python3
import subprocess
import os
import sys

dr = sys.argv[1]
chunksize = float(sys.argv[2])
os.chdir(dr)

files = os.listdir(dr)
n_files = len(files)

def compress(tar, files):
    command = ["tar", "-zcvf", "tarfile" + str(tar) + ".tar.gz", "-T", "-", "--null"]
    proc = subprocess.Popen(command, stdin=subprocess.PIPE)
    with proc:
        proc.stdin.write(b'\0'.join(map(str.encode, files)))
        proc.stdin.write(b'\0')
    if proc.returncode:
        sys.exit(proc.returncode)

sub = []; tar = 1; subsize = 0
for f in files:
    sub.append(f)
    subsize = subsize + (os.path.getsize(f)/1000000)
    if subsize >= chunksize:
        compress(tar, sub)
        sub = []; tar += 1; subsize = 0

if sub:
    # taking care of left
    compress(tar, sub)

실행하려면

python3 /path/tocompress_split.py /directory/with/files/tocompress chunksize

… chunksize는 tar 명령 의 입력 크기입니다 .

여기에는 @DavidFoerster가 제안한 개선 사항이 포함되어 있습니다. 감사합니다 많이 !


답변

순수한 쉘 접근법 :

files=(*);
num=$((${#files[@]}/8));
k=1
for ((i=0; i<${#files[@]}; i+=$num)); do
    tar cvzf files$k.tgz -- "${files[@]:$i:$num}"
    ((k++))
done

설명

  • files=(*): 파일 목록을 저장하십시오 (있는 경우 디렉토리 files=(*.txt), txt확장자 가있는 항목 만 가져 오도록 변경하십시오 ) $files.
  • num=$((${#files[@]}/8));: ${#files[@]}는 배열의 요소 수입니다 $files. 는 $(( ))연산을하는 떠들썩한 파티의 (제한적) 방법입니다. 따라서이 명령 $num은 파일 수를 8로 나눈 값으로 설정 합니다.
  • k=1 : tarball의 이름을 지정하는 카운터 일뿐입니다.
  • for ((i=0; i<${#files[@]}; i+=$num)); do: 배열의 값을 반복합니다. $i0배열의 첫 번째 요소 에서 초기화 되고 씩 증가합니다 $num. 이것은 우리가 모든 요소 (파일)를 겪을 때까지 계속됩니다.
  • tar cvzf files$i.tgz -- ${files[@]:$i:$num}: bash는, 당신은 사용하여 배열 슬라이스 (배열의 일부를) 얻을 수 ${array[@]:start:length}그래서, ${array[@]:2:3}두 번째부터 세 가지 요소를 반환합니다. 여기에서는 현재 값에서 시작하고 요소 길이 $i$num긴 슬라이스를 사용합니다 . 는 --로 시작할 수있는 파일 이름의 경우에 필요하다 -.
  • ((k++)) : 증분 $k