모든 하위 폴더의 모든 텍스트 파일을 하나의 거대한 텍스트 파일로 연결

모든 하위 폴더의 모든 텍스트 파일을 하나의 거대한 텍스트 파일로 연결

글쎄, 상황은 모두 동일한 이름의 프로필을 따르는 알 수 없는 수의 하위 디렉터리가 있다는 것입니다.

폴더 0, 폴더 1, 폴더 2, 폴더 3 등

이제 각 폴더에는 3개의 텍스트 파일이 있으며 이러한 텍스트 파일은 모든 폴더에서 동일한 3개의 파일 이름을 갖습니다.

파일 1 파일 2 파일 3

모든 폴더의 모든 텍스트 파일을 폴더 0, 파일 1, 파일 2, 파일 3부터 시작하여 모든 폴더에서 동일한 순서로 하나의 텍스트 파일로 연결하는 간단한 방법을 찾고 싶습니다.

이제 소수의 폴더에 대해 cat을 사용할 수 있습니다.

cat folder0/file1 folder0/file2 folder0/file3 folder1/file1 folder1/file2 folder1/file3 folder2/file1 folder2/file2 folder2/file3 folder3/file1 folder3/file2 folder3/file3 > textfile

하지만 폴더 수는 알 수 없습니다. 아마도 100개 또는 1000개일 것입니다.

이 작업을 수행할 수 있는 스크립트를 아는 사람이 있습니다.

답변1

Unix 도구와 파이프만 사용:

find ./ -type f -regex './folder[0-9]+/file[0-9]+' -print0 | sort -zV | xargs --null cat

설명하다:

find특정 기준과 일치하는 모든 파일 검색

  1. ./find현재 위치(즉, 작업 디렉터리)에서 검색하라고 지시합니다 .
  2. -type ffindfile이라는 디렉터리가 있는 경우에만 파일을 찾도록 지시합니다.
  3. -regexfind전체 경로가 주어진 패턴과 일치하는 파일만 검색함을 나타냅니다 . 이 경우 "./folder" 뒤에는 하나 이상의 숫자, 새 디렉터리, "file", 하나 이상의 숫자가 옵니다.
  4. -print0출력에 널 문자로 구분된 파일을 찾도록 지시합니다 find. 이는 파일 이름에 나타나지 않는 것이 보장되며 파일 이름에 개행 문자가 포함되어 있어도 작동합니다.

sort가져온 목록을 정렬합니다.

  1. 기본값인 개행 구분 항목 대신 널 문자 구분 항목을 -z정렬 하도록 지시합니다.sort
  2. 인간이 직관적으로 항목을 정렬하는 것처럼 항목을 정렬하도록 지시합니다 -V. 즉, 중간이 아닌 이후에 항목 을 정렬합니다.sortfile11file1file2

xargs가져온 항목을 사용하여 에 인수로 전달하면 cat짐작할 수 --null있듯이 xargs서로 다른 항목은 공백이나 개행 문자가 아닌 null 문자로 구분됩니다.

답변2

그리고 zsh:

autoload zargs
zargs -r -- folder<->/file<1-3>(nN) -- cat > hugefile

bash, 및 GNU 도구 사용 :

shopt -s extglob nullglob
print0() { (( $# == 0 )) || printf '%s\0' "$@"; }
 
xargs -r0a <(
  print0 folder+([0123456789])/file[123] | sort -zV
  ) cat > hugefile

그중에는 +([0123456789])( extglob를 포함하여 ksh의 고급 glob 연산자 중 일부를 활성화함 +(...)) zsh <->(ASCII 10진수 시퀀스)에 해당하는 것, sort -Vzsh의 nglob 한정자에 해당하는 GNU( 와 사이가 아닌 folder10뒤에 오도록 숫자를 정렬하는 데 사용됨 ), glob 한정자 의 경우 zsh 대신 GNU를 사용하여 목록을 분할합니다.folder9folder1folder2nullglobNxargszargs인수 목록이 너무 깁니다.실수.

우리는 print0인수를 NUL로 구분하여 인쇄하는 함수를 정의했습니다(bash에는 's가 없기 때문 zsh). 그러나 여기서는 파일 경로에 print -rNC1고유한 문자가 포함되지 않는다는 점을 고려하여 줄 바꿈으로 구분하여 인쇄하고 무시하는 것이 좋습니다. 사실: 목록이 비어 있으면 해당 줄은 무시되기 때문에 빈 줄을 인쇄합니다.xargs-0printf '%s\n'xargs

답변3

특정 폴더 수에 도달하면 다음을 수행할 수 있습니다.

cat folder*/* > file

또는 특정 파일/디렉토리에 대해서만:

cat {folder1,folder2,folder3}/{file1,file2,file3} > file

이름이 고정 문자열과 연속 숫자로 구성된 경우 다음과 같이 더 단순화할 수 있습니다.

cat folder{1..3}/file{1..3} > file

이제 파일과 폴더가 많으면 이 작업이 실패하지만 대부분의 경우에는 작동합니다. 예를 들어 내 컴퓨터에서 다음 명령을 사용하여 1000개의 디렉터리에 3000개의 파일을 만들었습니다.

mkdir folder{1..1000}
touch folder{1..1000}/file{1..3}
for f in */*; do echo "$f" > $f; done

그런 다음 모든 파일을 하나로 연결합니다.

cat folder*/* > file

이는 3000줄을 포함하는 파일을 제공합니다.

그러나 문제가 발생하면 언제든지 다음을 사용할 수 있습니다 find.

find folder1 folder2 folder3 -name "file[123]" -exec cat {} + > file

또는

find folder* -name "file[123]" -exec cat {} + > file

경고하다: 이러한 방법 중 어느 것도 순서를 지정할 수는 없지만 모든 디렉터리에서 동일한 순서를 가져야 합니다.

관련 정보