gzip 압축 파일 세트가 있고 이를 단일 파일로 결합하고 싶습니다. 각각은 동일한 형식을 갖습니다. 첫 번째 파일의 헤더 정보만 유지하고 다음 파일에서는 건너뛰고 싶습니다.
간단한 예로, 다음 내용을 포함하는 4개의 동일한 파일이 있습니다.
$ gzcat file1.gz
# header
1
2
나는 끝내고 싶다
# header
1
2
1
2
1
2
1
2
현실적으로 파일 수가 다를 수 있으므로 프로그래밍 방식으로 이 작업을 수행하고 싶습니다. 지금까지 제가 가지고 있는 비프로그래밍 솔루션은 다음과 같습니다.
cat <(gzcat file1.gz) <(tail -q -n +2 <(gzcat file2.gz) <(gzcat file3.gz) <(gzcat file4.gz))
명령은 작동하지만 4개의 파일을 처리하기 위해 "하드코드"되어 있으므로 이를 여러 파일에 일반화해야 합니다. 도움이된다면 bash
쉘을 사용하고 있습니다. 제가 선호하는 것은 성능입니다(실제로 파일 길이는 수백만 줄에 달할 수 있습니다). 따라서 속도가 빠르다면 덜 우아한 솔루션도 괜찮습니다.
답변1
질문에 표시한 명령이 기본적으로 작동하는 경우(하드코딩된 파일 수에 대해)
first=1
for f in file*.gz
do
if [ "$first" ]
then
gzcat "$f"
first=
else
gzcat "$f"| tail -n +2
fi
done > collection_single_file
당신을 위해 일해야합니다. 논리가 상당히 명확하기를 바랍니다. 모든 파일을 봅니다(파일 이름에 따라 와일드카드 변경). 목록의 첫 번째 파일인 경우 gzcat
전체 파일(헤더 포함)을 가져옵니다. 그렇지 않으면 tail
스트립 헤더를 사용하십시오. 한 파일이 처리되면 다른 파일은 더 이상 첫 번째 파일이 아닙니다.
이것은 전화할 것이다tail
질소한 번이 아니라 −1 번입니다(귀하의 답변과 같습니다). 그 외에는 내 대답이 당신의 대답과 같아야 합니다.
답변2
변종G-Man의 솔루션별도의 변수를 사용하지 않고 첫 번째 파일을 추적합니다.
set -- file*.gz
{
gzcat "$1"; shift
for file do
gzcat "$file" | sed '1d'
done
} >combined.txt
그러면 첫 번째 파일의 압축이 풀린 다음 나머지 파일을 반복하여 sed
첫 번째 줄을 제거하는 짧은 스크립트에 각 파일을 전달합니다. 출력이 로 리디렉션됩니다 combined.txt
.
이 set -- file*.gz
명령은 위치 인수( $1
, $2
등, 집합적으로 배열이라고 함 $@
)를 지정된 패턴과 일치하는 파일 이름으로 설정합니다. 압축을 푼 후 배열에서 shift
제거 합니다. $1
배열의 나머지 파일 이름을 반복합니다. 이는 다음과 같이 쓸 수도 있습니다.
for file in "$@"; do
gzcat "$file" | sed '1d'
done
이를 { ... }
통해 명령 출력을 한 번에 파일로 리디렉션할 수 있습니다.
더 짧게, "헤더 행"이 항상 문자로 시작하고 #
(질문의 예에서와 같이) 데이터에 다른 행이 없다고 가정하면 다음과 같습니다.
gzcat file*.gz | awk 'NR > 1 && /^#/ { next } 1' >combined.txt
또는,
gzcat file*.gz | sed '2,${ /^#/d; }' >combined.txt
#
압축되지 않은 데이터의 결합된 내용에서 두 번째 줄 이후에 나타나는 경우 두 방법 모두 처음부터 모든 줄을 건너뜁니다.