파일을 연결하는 가장 빠른 방법


25

총 20GB가 넘는 10k + 파일이 하나의 파일로 연결되어 있어야합니다.

보다 빠른 방법이 있습니까

cat input_file* >> out

?

선호되는 방법은 bash 명령이 될 것입니다. 파이썬도 상당히 느리지는 않지만 받아 들일 수 있습니다.


내 대답을 업데이트 find하고 셸 글로브와 같은 파일을 정렬하지 않습니다.
Graeme

5
시간이 99 % 시스템 I / O이므로 모든 (정상) 솔루션의 속도는 같습니다.
goldilocks


3
연결된 파일을 읽고있는 것과 다른 디스크에 쓰는 것을 고려하십시오.
Luis

1
out다른 디스크에 있으면 더 빠릅니다 .

답변:


30

아니, 고양이는 확실히 이것을하는 가장 좋은 방법입니다. 이 목적으로 C로 작성된 프로그램이있을 때 왜 파이썬을 사용합니까? 그러나 xargs명령 행 길이가 초과 ARG_MAX하고 둘 이상이 필요한 경우 사용을 고려할 수 있습니다 cat. GNU 도구를 사용하면 이는 이미 가지고있는 것과 동일합니다.

find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z |
  xargs -0 cat -- >>out

1
이 경우 파일을 순서대로 읽도록 할 수 있습니까?
Kiwy

1
예,의 출력이 find를 통해 전달 되기 때문 sort입니다. 이것이 없으면 파일은 임의의 순서 (파일 시스템에 의해 정의 된 파일 작성 순서 일 수 있음)로 나열됩니다.
scai

@scai 죄송하지만, 정렬이 매우 명확합니다
Kiwy

1
@Kiwy, 내가 볼 수있는 유일한 경우는 로케일이 환경에 올바르게 설정되어 있지 않으면 정렬과 bash글로브 가 다르게 작동 할 수 있다는 것 입니다. 그렇지 않으면 예상대로 작동 xargs하거나 cat작동 하지 않는 경우 가 표시되지 않습니다.
Graeme

3
@MarcvanLeeuwen, execve (2)의 E2BIG 오류를 피하기 위해 필요한만큼 xargs호출 cat합니다.
Stéphane Chazelas

21

출력 파일의 공간을 먼저 할당하면 시스템이 모든 쓰기에 대한 할당을 업데이트하지 않아도되므로 전체 속도가 향상 될 수 있습니다.

예를 들어 Linux의 경우 :

size=$({ find . -maxdepth 1 -type f -name 'input_file*' -printf '%s+'; echo 0;} | bc)
fallocate -l "$size" out &&
  find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z | xargs -r0 cat 1<> out

또 다른 이점은 사용 가능한 공간이 충분하지 않으면 복사가 시도되지 않는다는 것입니다.

에 만약 btrfs, 당신이 수 copy --reflink=always, 나머지를 추가 (데이터 복사하지 않으며, 따라서 거의 순간적인 것 의미) 첫 번째 파일. 10000 개의 파일이 있다면 첫 번째 파일이 매우 크지 않으면 큰 차이가 없을 것입니다.

모든 파일 ( BTRFS_IOC_CLONE_RANGE ioctl) 을 참조 복사하는 일반화하는 API가 있지만 API를 노출시키는 유틸리티를 찾을 수 없으므로 C (또는 python임의 ioctl의 s를 호출 할 수있는 다른 언어) 에서 수행해야합니다. .

소스 파일이 희소하거나 많은 NUL 문자 시퀀스가있는 경우 (GNU 시스템에서) 다음과 같이 희소 출력 파일 (시간 및 디스크 공간 절약)을 만들 수 있습니다.

find . -maxdepth 1 -type f -name 'input_file*' -print0 |
  sort -z | xargs -r0 cat | cp --sparse=always /dev/stdin out

1
@XTian은, 아니, 그것은 수 없습니다 둘 다해야합니다 >>>하지만, 1<>내가 말한대로 쓰기 파일.
Stéphane Chazelas

5
@grebneke <>는 표준 Bourne / POSIX 읽기 + 쓰기 리디렉션 연산자입니다. 자세한 내용은 쉘 설명서 또는 POSIX 사양 을 참조하십시오. 기본값은 fd입니다 0에 대한 <>연산자 ( <>대한 짧은 0<>처럼 <짧은입니다 0<>짧은 1>당신이 필요하므로) 1명시 적으로 리디렉션 표준 출력. 여기서는 읽기 + 쓰기 ( O_RDWR)가 필요하지 않지만 방금 할당 한 것을 할당 취소하는 O_TRUNC(와 같이 >) 원하지 않습니다 .
Stéphane Chazelas

1
@grebneke, unix.stackexchange.com/search?q=user%3A22565+%22%3C%3E%22 는 당신에게 몇 가지를 줄 것입니다. ksh93에는 탐색 연산자 BTW가 있으며 dd읽기를 통해 읽거나 읽을 수 있습니다.
Stéphane Chazelas

1
@ StephaneChazelas-많은 감사합니다. 도움과 지식은 대단히 감사합니다!
grebneke

1
나는 두 번째 라운드가 더 빠를지라도 fallocate여분의 오버 헤드를 무효화 할 많은 경우가있을 것이라고 확신하지 않습니다 find. btrfs그래도 흥미로운 가능성을 열어줍니다.
Graeme
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.