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

StackOverflow https://stackoverflow.com/questions/939982

  •  06-09-2019
  •  | 
  •  

문제

나는 일반적으로 다음을 수행합니다.

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

다른 팁

사용 -C 타르 스위치 :

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 구성 옵션이 있지만 제거되지는 않습니다. . 디렉토리 자체.명령을 길들이는 것이 점점 더 어려워집니다.

당신은 사용할 수 있습니다 $(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 tar가 상대 이름을 가진 파일의 위치를 ​​알 수 있도록 옵션이 필요합니다.그만큼 --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 -

이 답변 대부분의 상황에서 작동해야합니다. 그러나 파일 이름이 TAR 파일에 저장되는 방법에 주목하십시오. ./file1 단지보다는 file1. 이 방법을 사용하여 패키지 파일로 사용되는 Tarball을 조작 할 때 문제가 발생했음을 알았습니다. BuildRoot.

한 가지 해결책은 일부 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 *

Unix/Linux 시스템이고 숨겨진 파일 ( *에서 누락 될)에 관심이 있다면 다음을 수행해야합니다.

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

Windows에서 숨겨진 파일이 어떻게 보이는지 모르겠습니다.

다음의 배쉬 기능을 제안합니다 (첫 번째 인수는 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 ..

이것은 나에게 효과가 있었고 모든 파일을 ""라는 루트 디렉토리에 넣지 않고 숨겨진 모든 파일이 포함되어 있습니다. in처럼 토메의 대답 :

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' 또는 포함 된 파일을 제한하기 위해 찾기 명령과 유사한 필터.

 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`
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top