development

디렉토리 자체를 포함하지 않고 파일 및 폴더 디렉토리를 어떻게 tar합니까?

big-blog 2020. 2. 29. 15:25
반응형

디렉토리 자체를 포함하지 않고 파일 및 폴더 디렉토리를 어떻게 tar합니까?


나는 일반적으로 :

tar -czvf my_directory.tar.gz my_directory

my_directory에 모든 것 (숨겨진 시스템 파일 포함)을 포함 시키려고하지만 디렉토리 자체는 포함시키지 않으려면 어떻게해야합니까? 나는 원하지 않는다 :

my_directory
   --- my_file
   --- my_file
   --- my_file

내가 원하는:

my_file
my_file
my_file

cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd - 

한 줄로 작업을 수행해야합니다. 숨겨진 파일에도 잘 작동합니다. "*"는 적어도 bash에서 경로 이름 확장으로 숨겨진 파일을 확장하지 않습니다. 아래는 내 실험입니다.

$ mkdir my_directory
$ touch my_directory/file1
$ touch my_directory/file2
$ touch my_directory/.hiddenfile1
$ touch my_directory/.hiddenfile2
$ cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd ..
./
./file1
./file2
./.hiddenfile1
./.hiddenfile2
$ tar ztf my_dir.tgz
./
./file1
./file2
./.hiddenfile1
./.hiddenfile2

-Ctar 스위치를 사용하십시오 .

tar -czvf my_directory.tar.gz -C my_directory .

이 명령 -C my_directory은 tar에게 현재 디렉토리를로 변경하도록 지시 my_directory한 다음 ."현재 디렉토리 전체 추가"(숨겨진 파일 및 하위 디렉토리 포함)를 의미합니다.

수행 -C my_directory하기 전에 수행 해야합니다. 그렇지 .않으면 현재 디렉토리에 파일이 있습니다.


평소와 같이 아카이브를 작성하고 다음을 사용하여 추출 할 수도 있습니다.

tar --strip-components 1 -xvf my_directory.tar.gz

--transform/를 살펴보면 --xform파일이 아카이브에 추가 될 때 파일 이름을 마사지 할 수 있습니다.

% mkdir my_directory
% touch my_directory/file1
% touch my_directory/file2
% touch my_directory/.hiddenfile1
% touch my_directory/.hiddenfile2
% tar -v -c -f my_dir.tgz --xform='s,my_directory/,,' $(find my_directory -type f)
my_directory/file2
my_directory/.hiddenfile1
my_directory/.hiddenfile2
my_directory/file1
% tar -t -f my_dir.tgz 
file2
.hiddenfile1
.hiddenfile2
file1

변환 표현식은의 표현식과 유사 하며 위의 예제에서 ( sed이외의) 구분 기호를 사용할 수 있습니다 . https://www.gnu.org/software/tar/manual/html_section/tar_52.html/,


TL; DR

find /my/dir/ -printf "%P\n" | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

일부 조건 (파일, 디렉토리 및 심볼릭 링크 만 아카이브) :

find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

설명

아래는 불행히도 ./아카이브에 상위 디렉토리 포함되어 있습니다.

tar -czf mydir.tgz -C /my/dir .

--transform구성 옵션 을 사용하여 모든 파일을 해당 디렉토리 밖으로 이동할 수 있지만 .디렉토리 자체를 제거하지는 않습니다 . 명령을 길들이는 것이 점점 어려워지고 있습니다.

magnus 'answer$(find ...) 와 같이 명령에 파일 목록을 추가하는 데 사용할 수 있지만 "파일 목록이 너무 깁니다"오류가 발생할 수 있습니다. 가장 좋은 방법은 다음과 같이 tar 옵션 과 결합하는 것입니다 .-T

find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

기본적으로 디렉토리 아래의 모든 파일 ( -type f), 링크 ( -type l) 및 하위 디렉토리 ( -type d)를 나열 하고을 사용하여 모든 파일 이름을 상대적으로 -printf "%P\n"만든 다음 tar 명령으로 전달하십시오 (을 사용하여 STDIN에서 파일 이름을 가져옵니다 -T -). -C옵션은 상대 이름을 가진 파일의 위치 타르가 알 수 있도록 필요합니다. --no-recursion플래그는 tar가 아카이브하도록 지시 된 폴더로 중복되지 않도록합니다 (중복 파일을 야기 함).

파일 이름으로 특별한 작업을 수행해야하는 경우 (필터링, 심볼릭 링크 등)이 find명령은 매우 강력 tar하며 위 명령 일부를 제거하여 테스트 할 수 있습니다 .

$ find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d
> textfile.txt
> documentation.pdf
> subfolder2
> subfolder
> subfolder/.gitignore

예를 들어 PDF 파일을 필터링하려면 추가 ! -name '*.pdf'

$ find /my/dir/ -printf "%P\n" -type f ! -name '*.pdf' -o -type l -o -type d
> textfile.txt
> subfolder2
> subfolder
> subfolder/.gitignore

비 GNU 찾기

이 명령은 printf(GNU에서 사용 가능) 사용 하여 상대 경로로 결과를 인쇄하도록 find지시 find합니다. 그러나 GNU가없는 경우 find경로를 상대적으로 만들 수 있습니다 (부모를 제거하십시오 sed).

find /my/dir/ -type f -o -type l -o -type d | sed s,^/my/dir/,, | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -

이 답변 은 대부분의 상황에서 작동합니다. 그러나 파일 이름이 예를 들어 ./file1just가 아닌 tar 파일에 어떻게 저장되는지 확인하십시오 file1. BuildRoot 에서 패키지 파일로 사용되는 tarball을 조작하기 위해이 방법을 사용할 때 문제가 발생한다는 것을 알았습니다 .

한 가지 해결책은 Bash globs를 사용하여 다음을 제외한 모든 파일을 나열하는 것입니다 ...

tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *

이것은 이 답변 에서 배운 트릭 입니다.

이제 tar는 ..?*또는 일치하는 파일이 없으면 오류를 반환 .[^.]*하지만 여전히 작동합니다. 오류가 문제인 경우 (스크립트에서 성공을 확인하는 중) 다음과 같이 작동합니다.

shopt -s nullglob
tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *
shopt -u nullglob

지금은 쉘 옵션을 망쳐 놓고 있지만 *숨겨진 파일과 일치 하는 것이 더 깔끔하다고 결정할 수 있습니다.

shopt -s dotglob
tar -C my_dir -zcvf my_dir.tar.gz *
shopt -u dotglob

*현재 디렉토리에서 쉘이 차지하는 곳에서는 작동하지 않을 수도 있으므로 다음을 사용하십시오.

shopt -s dotglob
cd my_dir
tar -zcvf ../my_dir.tar.gz *
cd ..
shopt -u dotglob

cd my_directory
tar zcvf ../my_directory.tar.gz *

유닉스 / 리눅스 시스템이고 숨겨진 파일 (*에서 놓칠 수있는)에 관심이있는 경우 다음을 수행해야합니다.

cd my_directory
tar zcvf ../my_directory.tar.gz * .??*

Windows에서 숨겨진 파일의 모양을 모르겠습니다.


다음 Bash 함수를 제안합니다 (첫 번째 인수는 dir의 경로이고 두 번째 인수는 결과 아카이브의 기본 이름입니다).

function tar_dir_contents ()
{
    local DIRPATH="$1"
    local TARARCH="$2.tar.gz"
    local ORGIFS="$IFS"
    IFS=$'\n'
    tar -C "$DIRPATH" -czf "$TARARCH" $( ls -a "$DIRPATH" | grep -v '\(^\.$\)\|\(^\.\.$\)' )
    IFS="$ORGIFS"
}

이런 식으로 실행할 수 있습니다 :

$ tar_dir_contents /path/to/some/dir my_archive

my_archive.tar.gz현재 디렉토리 내에 아카이브를 생성합니다 . 숨겨진 (. *) 요소 및 파일 이름에 공백이있는 요소와 함께 작동합니다.


cd my_directory && tar -czvf ../my_directory.tar.gz $(ls -A) && cd ..

이것은 나를 위해 일했고 "."라는 루트 디렉토리에 모든 파일을 넣지 않고 모든 숨겨진 파일을 포함합니다. tomoe의 답변 에서처럼 :


pax를 사용하십시오.

Pax는 더 이상 사용되지 않는 패키지이지만 완벽하고 간단한 방식으로 작업을 수행합니다.

pax -w > mydir.tar mydir

내가 찾은 가장 간단한 방법 :

cd my_dir && tar -czvf ../my_dir.tar.gz *


# tar all files within and deeper in a given directory
# with no prefixes ( neither <directory>/ nor ./ )
# parameters: <source directory> <target archive file>
function tar_all_in_dir {
    { cd "$1" && find -type f -print0; } \
    | cut --zero-terminated --characters=3- \
    | tar --create --file="$2" --directory="$1" --null --files-from=-
}

공백이나 다른 특이한 문자로 파일 이름을 안전하게 처리합니다. 선택적으로 -name '*.sql'find 명령에 유사하거나 유사한 필터를 추가하여 포함 된 파일을 제한 할 수 있습니다.


 tar -cvzf  tarlearn.tar.gz --remove-files mytemp/*

폴더가 mytemp 인 경우 위를 적용하면 폴더의 모든 파일을 압축하여 제거하지만 혼자 두십시오.

 tar -cvzf  tarlearn.tar.gz --remove-files --exclude='*12_2008*' --no-recursion mytemp/*

제외 패턴을 지정하고 하위 폴더도 보지 않도록 지정할 수 있습니다


tar -C my_dir -zcvf my_dir.tar.gz `ls my_dir`

참고 URL : https://stackoverflow.com/questions/939982/how-do-i-tar-a-directory-of-files-and-folders-without-include-the-directory-it



반응형