Bash 스크립트를 사용하여 하위 디렉터리에서 tar 아카이브 찾기

Bash 스크립트를 사용하여 하위 디렉터리에서 tar 아카이브 찾기

많은(>5000) 폴더가 있는 디렉토리가 있습니다.

folder1
folder2
folder3
...

이러한 모든 폴더에는 많은 하위 디렉터리가 있습니다. 각 폴더의 특정 하위 디렉터리에 tar.gz아카이브가 있을 수 있습니다. 폴더에 tar.gz아카이브가 포함된 경우 해당 아카이브는 하나만 있으며 특정 하위 디렉터리에 있습니다.

예를 들어:

folder1/foo/baz.tar.gz
folder2/bar/qux.tar.gz
folder3 [no tar.gz file in this folder]
...

다음 작업을 수행하려면 bash 스크립트를 작성해야 합니다.

  • tar.gz각 폴더를 반복하면서 아카이브(존재하는 경우)를 찾고 해당 콘텐츠를 다른 디렉터리(발견된 모든 아카이브에 대해 동일)에 추출하고 싶습니다 .
  • 각 아카이브를 찾은 후에는 아카이브가 저장된 경로와 함께 아카이브와 동일한 디렉터리에 더 많은 파일을 이동 tar.gz해야 합니다 .tar.gz

모든 아카이브를 나열할 수 있습니다.

find . -name "*tar.gz"

얻은 명령을 조작하는 것이 최선의 해결책인지, 아니면 각 디렉토리를 반복하는 것이 더 나은지 궁금합니다.

가장 최적화된 접근 방식은 무엇입니까? 이 작업을 어떻게 수행해야 합니까?

답변1

find기본적으로 옵션에서 단일 작업이나 작업 목록을 수행할 수 있습니다 -exec. 그렇다면 untar각 아카이브를 에서 수행하는 것은 어떨까요 find -exec? 복잡한 명령의 경우 이 -exec함수를 사용하여 쉘을 호출하고 -c쉘 명령의 옵션을 사용하여 실행할 실제 명령을 전달하는 것이 일반적입니다 . 예를 들어(실제로 이 실용적인 예제를 수행하는 더 쉬운 방법이 있지만 이는 아이디어를 보여주기 위한 것입니다):

-exec sh -c 'mv "$1" "~/$1"' sh {} ';'

그러면 발견된 각 파일에 대해 셸이 시작되고 해당 파일이 $HOME디렉터리로 이동됩니다. 발견된 파일 이름을 쉘 위치 인수로 전달하는 데 {}사용됩니다. 이므로 $1쉘 명령에서 가 대신 $1사용됩니다 {}. 귀하의 경우 이러한 유형의 솔루션은 다음과 같습니다.

-exec sh -c 'tar xvf "$1" -C "$(dirname $1)"' sh {} ';' 

아이디어는 이 관용구가 여러분이 선호하는 쉘의 모든 기능을 제공한다는 것입니다.이내에주문하다 find. (예, 대신 bash또는 를 사용할 수 있습니다 . 단, 로딩 속도가 훨씬 빠르며 많은 파일로 작업할 때 속도가 빨라질 수 있다는 점에 유의하세요 .)zshshsh

반복적으로 수행하는 작업이거나 시간이 오래 걸릴 것으로 예상되는 경우,그리고멀티 코어 CPU가 있는 경우 두 번째 옵션을 고려하는 것이 유리할 수 있습니다. 즉, GNU 파이프를 통해 파일 목록을 파이프 하고 모든 코어에서 동시에 작업을 수행하도록 parallel하는 것입니다 . untar초보자는 다음을 시도해 볼 수 있습니다.

find . -name "*tar.gz" -type f -print0 |
  parallel -0 tar xvf {} -C {//}

dirname효율성을 높이기 위해 위의 답변을 사용하면 GNU Parallel 자체가 더 효율적으로 수행할 수 있으므로 외부 명령을 사용할 필요가 없습니다 . 이것이 {//}그들이 하는 일입니다.

경고: 저는 이에 대한 전문가가 아니며 parallel실제 사용 경험 없이 이 옵션을 제공하므로 이것이 올바른 접근 방식인지 다른 사람들이 의견을 제시할 수 있다면 좋을 것입니다.

답변2

find 명령을 사용하여 압축을 풀 수 있는 스크립트에 tarball 경로를 전달할 수 있습니다(아직 테스트하지 않았습니다).

$ cat script
#!/bin/bash --
tarball="${1}"
dir="$(dirname ${tarball})"
tar xvf "${tarball}" -C "${dir}"

그런 다음 find를 사용하여 스크립트를 호출합니다.

$ find . -type f -name '*.tar.gz' -exec ./script "{}" \;

또는 find 명령에서(빠른 테스트):

find . -type f -name '*.tar.gz' -exec sh -c 'dir="$(dirname ''"{}"'')"; tar xvf "{}" -C "${dir}"' \;

관련 정보