[unix] 큰 파일을 복사하지 않고 서로 추가

디스크에 남은 여유 공간이 각각 10G 인 5 개의 거대한 파일 (file1, file2, .. file5)이 있으며이 모든 파일을 하나로 연결해야합니다. 원본 파일을 유지할 필요는 없으며 마지막 파일 만 보관하십시오.

일반적인 연결은 함께가는 cat파일을 순서대로 file2.. file5:

cat file2 >> file1 ; rm file2

불행히도이 방법은 내가 가지고 있지 않은 최소 10G 여유 공간이 필요합니다. 실제로 복사하지 않고 파일을 연결하는 방법이 있지만 파일 시스템에 어떻게 든 file1이 원래 file1 끝에서 끝나지 않고 file2 시작에서 계속된다고 알려주십시오.

추신. 중요한 경우 파일 시스템은 ext4입니다.



답변

AFAIK (불행히도) 처음부터 파일을 자르는 것은 불가능합니다 (표준 툴에서는 가능하지만 syscall 레벨 은 여기를 참조하십시오 ). 그러나 약간의 복잡성을 추가하면 일반 잘림을 사용할 수 있습니다 (드문 파일과 함께). 사이에 모든 데이터를 쓰지 않고도 대상 파일의 끝에 쓸 수 있습니다.

먼저 두 파일이 모두 정확히 5GiB (5120MiB)이고 한 번에 100MiB를 이동한다고 가정하겠습니다. 당신은 다음으로 구성된 루프를 실행합니다

  1. 소스 파일의 끝에서 대상 파일의 끝으로 하나의 블록 복사 (사용 된 디스크 공간 늘리기)
  2. 소스 파일을 한 블록 씩 잘라 내기 (디스크 공간 확보)

    for((i=5119;i>=0;i--)); do
      dd if=sourcefile of=targetfile bs=1M skip="$i" seek="$i" count=1
      dd if=/dev/zero of=sourcefile bs=1M count=0 seek="$i"
    done
    

그러나 작은 테스트 파일을 먼저 사용해보십시오. 제발 …

파일 크기가 같거나 블록 크기의 배수가 아닐 수 있습니다. 이 경우 오프셋 계산이 더 복잡해집니다. seek_bytes그리고 skip_bytes나서 사용해야합니다.

이것이 당신이 가고 싶지만 세부 사항에 대한 도움이 필요하다면 다시 요청하십시오.

경고

에 따라 dd블록 크기 결과 파일은 조각의 악몽이 될 것입니다.


답변

프로그램이 여러 파일을 처리 할 수없는 경우 파일을 하나의 파일로 묶는 대신 명명 된 파이프를 사용하여 단일 파일을 시뮬레이션 할 수 있습니다.

mkfifo /tmp/file
cat file* >/tmp/file &
blahblah /tmp/file
rm /tmp/file

Hauke가 제안한 것처럼 losetup / dmsetup도 작동 할 수 있습니다. 빠른 실험; 나는 ‘file1..file4’를 만들었고 약간의 노력으로 다음을 수행했습니다.

for i in file*;do losetup -f ~/$i;done

numchunks=3
for i in `seq 0 $numchunks`; do
        sizeinsectors=$((`ls -l file$i | awk '{print $5}'`/512))
        startsector=$(($i*$sizeinsectors))
        echo "$startsector $sizeinsectors linear /dev/loop$i 0"
done | dmsetup create joined

그런 다음 / dev / dm-0에는 파일을 내용으로 사용하는 가상 블록 장치가 포함됩니다.

나는 이것을 잘 테스트하지 못했습니다.

또 다른 편집 : 파일 크기는 512로 균등하게 나눠야합니다. 그렇지 않으면 일부 데이터가 손실됩니다. 그렇다면 괜찮습니다. 나는 그가 또한 아래에 언급 한 것을 본다.


답변

사용 가능한 여유 공간만큼 많은 데이터를 묶음으로 복사하는 것을 작성해야합니다. 다음과 같이 작동합니다.

  • 읽기 전에 올바른 위치를 찾아서 file2사용하여 데이터 블록을 pread()읽습니다.
  • 에 블록을 추가하십시오 file1.
  • fcntl(F_FREESP)에서 공간을 할당 해제하는 데 사용 합니다 file2.
  • 반복

답변

나는 그것이 당신이 요청한 것보다 더 많은 해결 방법이라는 것을 알고 있지만 문제를 해결할 것입니다 (그리고 조각화 또는 헤드 스크래치가 거의 없음).

#step 1
mount /path/to/... /the/new/fs #mount a new filesystem (from NFS? or an external usb disk?)

그리고

#step 2:
cat file* > /the/new/fs/fullfile

또는 압축이 도움이된다고 생각하는 경우 :

#step 2 (alternate):
cat file* | gzip -c - > /the/new/fs/fullfile.gz

그런 다음 마지막으로

#step 3:
rm file*
mv /the/new/fs/fullfile  .   #of fullfile.gz if you compressed it


답변