30000개의 txt 파일이 있는 폴더가 있는데 각 파일의 크기는 50-60kb입니다. 2.5mb txt 파일로 병합해야 합니다. 그리고 병합 중인 파일을 삭제하세요. 내 코드는 다음과 같아야 합니다. for f in *,50; do cat file1,file2...file49 > somefile.txt;done
물론 이것은 의사 코드입니다. 파일을 50개 묶음으로 병합한 다음 사용한 파일을 삭제해야 합니다. 누구든지 나를 도와줄 수 있나요?
답변1
그리고 zsh
:
files=( ./input-file*(Nn.) )
typeset -Z3 n=1
while
(( $#files > 0 )) &&
cat $files[1,50] > merged-file$n.txt &&
rm -f $files[1,50]
do
files[1,50]=()
((n++))
done
./input-file*(Nn.)
일치하는 파일로 확장되지만 ./input-file*
3개의 전역 한정자를 사용하여 추가로 분류됩니다.
N
:nullglob: 일치하는 항목이 없을 경우 오류로 인해 중단되는 대신 glob 확장을 null로 만듭니다. glob에서 배열을 설정할 때 종종 이것이 필요하며 배열이 비어 있어도 괜찮습니다.n
:numericglobsort
: 기본 어휘 정렬을 숫자 정렬(실제로는 둘의 조합)로 변경합니다. 즉,input-file2
앞쪽 정렬입니다.input-file10
.
: 제한된정기적인파일(디렉토리, 심볼릭 링크, FIFO 무시...)
typeset -Z3 n
$n
너비가 3이 될 때까지 변수를 0으로 채워서 다음을 얻습니다 merged-file001.txt
. ... merged-file049.txt
...
그런 다음 배열에 요소가 있고 오류가 없는 한 $files
한 번에 50개의 배치(및 마지막 배치에서 남은 모든 요소)를 연결하여 반복합니다 .
bash 4.4+ 및 GNU 도구에도 동일하게 적용됩니다.
readarray -td '' files < <(
LC_ALL=C find . -maxdepth 1 -name 'input-file*' -type f -print0 |
sort -zV
)
n=0
set -- "${files[@]}"
while
(( $# > 0 )) &&
printf -v padded_n %03d "$n" &&
cat "${@:0:50}" > "merged-file$padded_n.txt" &&
rm -f "${@:0:50}"
do
shift "$(( $# >= 50 ? 50 : $# ))"
((n++))
done
find
zsh가 작동하는 경우 ./input-file*(N.)
숫자 sort -V
(버전) 정렬에서는 위치 인수를 사용하고 배열이 매우 제한되어 있으므로 shift
루프에서 배열을 사용합니다 .bash
답변2
이 스크립트는 다음과 같습니다.
- Bash의 경우(태그 지정됨)
- 조회 방지(잘못된 문자로 인해 실패)
- 일반 파일(디렉토리 없음)만 처리되는지 확인하세요.
sort
숫자로(음, 버전별로) 정렬 하고- 연결
k
파일(변수 개수) - 제거하다하나파일 한 번(삭제되지 않는 파일 블록 복사 방지)
dir="myDir"
readarray -td $'\0' files < <(
for f in ./"$dir"/in-file*; do
if [[ -f "$f" ]]; then printf '%s\0' "$f"; fi
done |
sort -zV
)
k=50
rm -f ./"$dir"/joined-files*.txt
for i in "${!files[@]}"; do
n=$((i/k+1))
cat "${files[i]}" >> ./"$dir"/joined-files$n.txt &&
rm -f "${files[i]}"
done