수천 개의 작은 텍스트 파일을 하나의 큰 텍스트 파일로 병합하고 싶습니다. 나는 그것들을 다음 구조의 디렉토리에 넣었습니다: timestamp1/status.txt
. 예를 들어: 20130430133144/status.txt
. 지금까지 나는 알고 있다
cat */* > bigtextfile.txt
적은 수의 파일에 적합합니다. 그러나 더 높은 숫자에도 작동합니까? cat
모든 파일의 내용을 수집한 다음 에 저장하려고 하는지 궁금합니다 . 그렇지 않으면 파일을 가져와서 에 추가한 다음 다른 파일을 가져오는 bigtextfile
등의 다른 방법이 있어야 할 것 같습니다 . bigtextfile
등등의 비유.
답변1
존재하다:
cat */* > bigtextfile.txt
쉘은 */*
(숨겨지지 않은) 일치하는 파일의 정렬된 목록으로 확장되고 cat
이러한 파일 경로를 인수로 사용하여 실행됩니다.
cat
각 파일은 차례로 열리고 파일에서 읽은 내용이 표준 출력에 기록됩니다. cat
한 번에 메모리에 보관되는 데이터로 가득 찬 버퍼(몇 킬로바이트 정도)는 두 개 이상 없습니다.
그러나 발생할 수 있는 한 가지 문제는 매개변수 목록이 cat
너무 커서 execve()
시스템 호출 매개변수 크기 제한에 도달한다는 것입니다. 따라서 파일 목록을 분할하여 cat
여러 번 실행해야 할 수도 있습니다 .
이것을 사용할 수 있습니다 xargs
(여기에서는 GNU 또는 BSD를 xargs
비표준 -r
및 -0
옵션으로 사용).
printf '%s\0' */* | xargs -r0 cat -- > big-file.txt
( printf
셸에 내장되어 있기 때문에 시스템콜을 거치지 않으므로 execve
, 제약사항을 거치지 않습니다.)
또는 find
파일 목록을 만들고 필요한 만큼 cat 명령을 실행합니다.
find . -mindepth 2 -maxdepth 2 -type f -exec cat {} + > big-file.txt
또는 휴대용:
find . -path './*/*' -prune -type f -exec cat {} + > big-file.txt
*/*
( 디렉토리의 심볼릭 링크에서 파일을 찾는 대신 숨겨진 파일(및 숨겨진 디렉터리의 파일)을 포함하며 파일 목록은 정렬되지 않습니다.)
최신 버전의 Linux를 사용하는 경우 다음을 수행하여 매개변수 크기 제한을 제거할 수 있습니다.
ulimit -s unlimited
cat -- */* > big-file.txt
Pass zsh
, 다음을 사용할 수도 있습니다 zargs
.
autoload zargs
zargs -- */* -- cat > big-file.txt
Pass 다음을 ksh93
사용할 수 있습니다 command -x
.
command -x cat -- */* > big-file.txt
이들 모두는 동일한 작업을 수행하며 파일 목록을 분할하고 cat
필요한 만큼 많은 명령을 실행합니다.
이번에도 내장 명령을 사용하여 ksh93
제한 사항을 해결할 수 있습니다.execve()
cat
command /opt/ast/bin/cat -- */* > big-file.txt
답변2
아니요는 cat
쓰기를 시작하기 전에 모든 파일을 버퍼링하지 않습니다.
그러나 파일 수가 많은 경우 에 전달된 인수 수에 문제가 발생할 수 있습니다 cat
. 기본적으로 Linux 커널은 모든 프로그램에 고정된 수의 인수만 전달하도록 허용합니다(값을 얻는 방법은 기억나지 않지만 대부분의 경우 수천 개입니다).
이 문제를 해결하려면 다음을 수행할 수 있습니다.
find -mindepth 2 -maxdepth 2 -type f -exec cat {} \; > bigtextfile.txt
이것은 기본적으로 cat
발견된 각 파일에 대해 개별적으로 find
.
답변3
파일 수가 너무 많으면 */*
너무 큰 매개변수 목록이 제공됩니다. 그렇다면 다음을 수행할 수 있습니다.
find . -name "*.txt" | xargs cat > outfile
(아이디어는 다음을 사용하여 find
파일 xargs
이름을 cat
가져오는 xargs
것 입니다.outfile