somente arquivos tar, sem diretórios

16

Provavelmente posso escrever um script de shell para encontrar apenas arquivos e passar a lista para tar, mas estou me perguntando se já existe um recurso interno no tar que permita fazer exatamente isso, em uma única linha de comando?

Por exemplo, encontrei a --no-recursionopção, mas quando o faço:

tar --no-recursion -cvf mydir.tar mydir

Ele apenas arquiva os nomes das entradas no diretório (incluindo subdiretórios!), Mas não arquiva nenhum arquivo.

Eu também tentei:

 tar --no-recursion -cvf mydir.tar mydir/*

Mas, embora arquive apenas arquivos, também arquiva os nomes dos subdiretórios.

Existe uma maneira de dizer apenas arquivos tar, sem diretórios?

ateiob
fonte
5
Apenas para esclarecer: você deseja criar um arquivo com estrutura "plana" (ou seja, todos os arquivos misturados em um diretório)?
rozcietrzewiacz
11
Você pode criar um novo diretório find mydir -type f |xargs cp -t tempdire, em seguida, tar tempdir.
18711 Kevin
@rozcietrzewiacz Sim, simples, mas apenas desse diretório, não de subdiretórios.
ateiob
11
OK, acho que vejo o que você está tentando fazer. Como sobrefind mydir -depth 1 -type f | xargs tar cf mydir.tar
Kevin
2
Ah, espaços. Use achado é -exec vez: find mydir -maxdepth 1 -type f -exec tar cvf mydir.tar {} +. Os +puts todos os arquivos na mesma linha de comando como xargs.
18711 Kevin

Respostas:

11

Camh ressalta que o comando anterior apresentava um pequeno problema, dado que muitos nomes de arquivos eram executados mais de uma vez, com invocações posteriores eliminando silenciosamente as execuções anteriores. Como não estamos compactando também, podemos acrescentar em vez de substituir:

find mydir -maxdepth 1 -type f -print0 | xargs -0 tar Avf mydir.tar
find mydir -maxdepth 1 -type f -exec tar Avf mydir.tar {} +

A resposta de Iocnarz de usar tar's' --nulle -Topções também funciona. Se você cpioinstalou, a resposta do camh também é boa. E se você tem zshe não se importa de usá-lo para um comando, a resposta de Gilles usando um zsh glob ( *(.)) parece a mais direta.


A chave era a -maxdepthopção. Resposta final, lidando com os espaços adequadamente:

find mydir -maxdepth 1 -type f -print0 | xargs -0 tar cvf mydir.tar

Isso também deve funcionar:

find mydir -maxdepth 1 -type f -exec tar cvf mydir.tar {} +
Kevin
fonte
4
Ambos podem resultar em várias invocações de tar. Ambos xargse findcom a +variante têm um número máximo de argumentos que podem ser passados ​​para o tar. Isso resultará na segunda invocação do tar, substituindo a saída da primeira.
Camh
2
Expandindo o limite de xargs, os xargs são padronizados para uma linha de comando máxima de 128KiB. Se a lista de arquivos for maior, você recebe uma segunda (ou mais) invocação do comando (tar), levando à perda de dados silenciosa. Você pode usar -xpara forçar o xargs a falhar em vez de perder dados e, embora seja melhor que um bug silencioso de perda de dados, ainda não é o ideal. Esse bug de classificação é tão perigoso porque tudo parece bem no início, mas à medida que a lista de arquivos aumenta com o tempo, você começa a acioná-lo e pode não perceber até tentar restaurar o backup. Então é tarde demais.
CAMH
@camh Você está certo, obrigado por apontar isso; Eu atualizei para refletir isso.
Kevin
11
A "resposta final" não está correta; se você usar "tar c" sem -T, poderá obter resultados parciais.
Eckes
14

Quando você quiser usar findcom tar, a melhor maneira é usar cpioem vez de tar. cpiopode gravar arquivos tar e foi projetado para levar a lista de arquivos a serem armazenados no stdin.

find mydir -maxdepth 1 -type f -print0 | cpio -o -H ustar -0 > mydir.tar

Usando finde cpioé uma abordagem mais unix-y, na medida em que você deixa finda seleção de arquivos com todo o poder que ela tem e deixa cpiofazer o arquivamento. Vale a pena aprender esse uso simples cpio, pois você acha fácil resolver problemas com os quais se esforça ao tentar tar.

camh
fonte
Brilhante! Eu usei o cpio em um passado distante, mas nunca soube da opção ustar.
Ian McGowan
2
Isso funcionou muito melhor para mim do que a resposta aceita.
Dale Anderson
11
apenas um nit. o -maxdepth 1 deve vir antes do -type f ou você vai receber um aviso de alguns achados
kdubs
Obrigado @kdubs. Eu atualizei a resposta para colocar -maxdepthantes -type.
Camh
3

Não sei se entendi seus requisitos. Se você deseja armazenar os arquivos regulares em mydirseus subdiretórios, mas não em seus subdiretórios, a maneira mais fácil é usar o zsh, onde a correspondência de arquivos regulares é apenas uma questão simples de usar o . qualificador global :

tar cf mydir.tar mydir/*(.)
Gilles 'SO- parar de ser mau'
fonte
3

Você pode até usar find ... -print0e tar ... --nulldiretamente sem usar xargs.

find . -maxdepth 1 -type f -print0 | tar cvf mydir.tar --null -T -

No exemplo dado, a --no-recursionopção to tarnão é necessária porque apenas os caminhos dos arquivos (e não os diretórios) serão transmitidos de findpara tar.

Usar a --no-recursionopção tarno exemplo a seguir, no entanto, impede a tarduplicação de diretórios de arquivamento. findfará a recursão da árvore de diretórios em vez tardisso.

# compare
find . -print0 | tar cf mydir.tar --null -T -
tar -tf mydir.tar | nl

find . -print0 | tar cf mydir.tar --null --no-recursion -T -
tar -tf mydir.tar | nl
locnarz
fonte
2

Como o parágrafo introdutório man tardiz (última frase),

O uso de um nome de diretório sempre implica que os subdiretórios abaixo devem ser incluídos no arquivo morto.

Que entendo como uma resposta "não" à sua pergunta.

rozcietrzewiacz
fonte
Boa captura, excepto que agora inclui numerosas alcatrão meachisms de exclusão (por exemplo --no-recursion, --exclude-tag, etc.). Estou olhando para o --exclude-tagque parece promissor, mas parece ser exatamente o oposto do que estou procurando.
ateiob
Eu tentei isso e vi personagens sendo removidos de nomes de caminho longos. Usar tar com -T e --null como camh proposto evitou esse problema.
Paul Brannan
1
star -c -C startdir -find . ! -type d > out.tar

Omitir -C startdire substituir. por startdirse ele aparecer no arquivo morto.

Este é o método mais eficiente baseado nos recursos do libfind. O Libfind também oferece primárias -chown -chgrp -chmodque modificam o stat de estrutura e permitem arquivar diferentes metadados. Isso também funciona no modo de lista e extração e evita a necessidade de extrair o arquivo inteiro em muitos casos.

esperto
fonte
Você pode usar -findno -copymodo A sinopse da página de manual sugere que você pode, mas não consegui fazê-lo funcionar (enquanto tentava responder Como copiar arquivos modificados, preservando a estrutura de pastas ) (com schily-2016-02-10)
Stéphane Chazelas
Não testei isso por mais tempo. Pode ser que haja um erro no momento. A página de manual diz que o último argumento seria o diretório de extração, mas quando eu tento isso, recebo: "Argumentos de caminho ainda não suportados no modo de extração". É isso que você ganha quando tenta?
schily
sim. A página de manual também diz que você só pode encontrar argumentos depois de -find, mas se eu colocar o diretório de destino antes de -find, também recebo um erro #
#:
Há um código para desativar o código de localização no processo de extração e a mensagem de erro é de uma verificação incorreta que espera -c, mas também deve permitir -copy. No modo -copy, o analisador de localização não deve incluir o último argumento.
schily
11
Agora, uma solução final foi publicada nas ferramentas inteligentes em sourceforge.net/projects/schilytools/files/schily-2016-03-11.tar.bz2. Isso também corrige um problema de um setlocale () ausente em estrela e permite: C directrory para star -find.
schily 11/03
0

Eu poderia ter encontrado uma solução.

find mydir -type f -printf '%P\0'|tar czvf mydir.tar.gz -C mydir --null -T -

Isso pode custar um pouco, mas de qualquer maneira funcionará, porque isso não depende do xargs.

ciel
fonte
-1

dir = seu_dir; cd $ dir; tar -cvf file.tar `find. -maxdepth 1 -type f -print`

H Bosch
fonte