Como posso tar um diretório de arquivos e pastas sem incluir o próprio diretório?

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

  •  06-09-2019
  •  | 
  •  

Pergunta

Eu normalmente fazer:

tar -czvf my_directory.tar.gz my_directory

E se eu só quero incluir tudo (incluindo quaisquer arquivos de sistema ocultos) em my_directory, mas não o próprio diretório? Eu não quero:

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

Eu quero:

my_file
my_file
my_file
Foi útil?

Solução

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

deve fazer o trabalho em uma linha. Ele funciona bem para arquivos ocultos também. "*" Não expande arquivos escondidos por expansão nome do caminho, pelo menos em bash. Abaixo está a minha experiência:

$ 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

Outras dicas

Use o interruptor -C de alcatrão:

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

O -C my_directory diz tar para alterar o diretório atual para my_directory, e depois meio . "adicionar o diretório atual inteira" (incluindo arquivos ocultos e sub-diretórios).

Certifique-se de fazer -C my_directory antes de fazer . ou então você vai obter os arquivos no diretório atual.

Você também pode criar arquivo como de costume e extraí-lo com:

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

Tenha um olhar em --transform / --xform, dá-lhe a oportunidade de massagear o nome do arquivo como o arquivo é adicionado ao arquivo:

% 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

Transform expressão é semelhante ao de sed, e podemos usar diferentes / separadores (, no exemplo acima).
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 -

Com algumas condições (arquivar apenas arquivos, diretórios e links simbólicos):

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

Explicação

A seguir, infelizmente, inclui um ./ diretório pai no arquivo:

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

Você pode mover todos os arquivos fora desse diretório usando a opção de configuração --transform, mas isso não se livrar do diretório . si. Torna-se cada vez mais difícil de domar o comando.

Você pode usar $(find ...) para adicionar uma lista de arquivos para o comando (como em magnus' resposta ), mas que potencialmente provoca uma "lista de arquivo muito longo" erro. A melhor maneira é combiná-lo com a opção -T de alcatrão, como este:

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

Basicamente o que ele faz é listar todos os arquivos (-type f), links (-type l) e subdiretórios (-type d) sob seu diretório, fazer todos os nomes de arquivos relativa utilizando -printf "%P\n", e, em seguida, passar isso para o comando tar (leva nomes de arquivos a partir de STDIN usando -T -). A opção -C é necessário para tar sabe onde estão os arquivos com nomes relativos estão localizados. A bandeira --no-recursion é para que o alcatrão não recurse em pastas que é dito para arquivo (causando arquivos duplicados).

Se você precisa fazer algo especial com nomes de arquivos (filtragem, seguintes links simbólicos, etc), o comando find é muito poderoso, e você pode testá-lo por apenas removendo a parte tar do comando acima:

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

Por exemplo, se você quiser arquivos PDF de filtro, adicione ! -name '*.pdf'

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

Não-GNU encontrar

O comando usa printf (disponível em GNU find) que diz find para imprimir seus resultados com caminhos relativos. No entanto, se você não tem GNU find, isso funciona para fazer os caminhos relativos (remove pais com 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 -

Este Resposta deve funcionar na maioria das situações. Aviso no entanto como os nomes de arquivos são armazenados no arquivo tar como, por exemplo, ./file1 ao invés de apenas file1. Descobri que este problemas causados ??quando usar este método para manipular tarballs usados ??como arquivos de pacotes em BuildRoot .

Uma solução é usar algum Bash globs para listar todos os arquivos exceto para .. assim:

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

Este é um truque que aprendi com esta resposta .

Agora tar retornará um erro se não há arquivos ..?* ou .[^.]* correspondentes, mas ainda vai funcionar. Se o erro é um problema (que está a verificar para o sucesso em um script), isso funciona:

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

Embora agora estamos mexendo com opções de shell, que pode decidir que é mais puro que ter jogo * arquivos escondidos:

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

Este pode não funcionar onde seu shell globs * no diretório atual, então, alternativamente, use:

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 *

Se é um sistema Unix / Linux, e você se preocupa com arquivos ocultos (que não será atingido por *), você precisa fazer:

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

Eu não sei o que arquivos escondidos olhar como no Windows.

Eu proporia a seguinte função Bash (primeiro argumento é o caminho para a dir, segundo argumento é o nome base resultante de arquivo):

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"
}

Você pode executá-lo da seguinte maneira:

$ tar_dir_contents /path/to/some/dir my_archive

e vai gerar o my_archive.tar.gz arquivo dentro do diretório atual. Ele funciona com oculto (. *) Elementos e com elementos com espaços em seu nome.

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

Este trabalhou para mim e é incluir todos os arquivos ocultos, sem colocar todos os arquivos em um diretório raiz com o nome "" como em de Tomoe resposta :

Use pax.

Pax é um pacote obsoleto, mas faz o trabalho perfeitamente e de forma simples.

pax -w > mydir.tar mydir

Mais simples maneira que eu encontrei:

cd meu_diretório && 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=-
}

segurança lida com nomes de arquivos com espaços ou outros caracteres incomuns. Opcionalmente, é possível adicionar um -name '*.sql' ou filtro semelhante ao comando find para limitar os arquivos incluídos.

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

Se a pasta é mytemp em seguida, se você aplicar o que precede, vai zip e remover todos os arquivos na pasta, mas deixá-lo sozinho

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

Você pode dar excluir padrões e também especificar para não olhar em subpastas demasiado

tar -C my_dir -zcvf my_dir.tar.gz `ls my_dir`
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top