O comando find fornece esta saída:
[root @ localhost /] # encontra var / log / -iname anaconda. * var / log / anaconda.log var / log / anaconda.xlog var / log / anaconda.yum.log var / log / anaconda.syslog var / log / anaconda.program.log var / log / anaconda.storage.log
Depois de combinar com o tar, está mostrando esta saída:
[root @ localhost /] # encontra var / log / -nome anaconda. * -exec tar -cvf file.tar {} \; var / log / anaconda.log var / log / anaconda.xlog var / log / anaconda.yum.log var / log / anaconda.syslog var / log / anaconda.program.log var / log / anaconda.storage.log
Mas ao listar o arquivo tar, ele mostra apenas um único arquivo
[root @ localhost /] # tar -tvf file.tar -rw ------- root / root 208454 27-02-2012 12:01 var / log / anaconda.storage.log
O que estou fazendo de errado aqui?
Com xargs, estou recebendo esta saída:
[root @ localhost /] # encontra var / log / -iname anaconda. * | xargs tar -cvf file1.tar
Segunda questão
Ao digitar / na frente de var, significa find /var/log
por que está dando a essa mesaage tar: Removendo `/ 'principal dos nomes dos membros
[root @ localhost /] # find / var / log / -nome anaconda. * -exec tar -cvf file.tar {} \; tar: Removendo `/ 'principal dos nomes dos membros /var/log/anaconda.log tar: Removendo `/ 'principal dos nomes dos membros /var/log/anaconda.xlog tar: Removendo `/ 'principal dos nomes dos membros /var/log/anaconda.yum.log tar: Removendo `/ 'principal dos nomes dos membros /var/log/anaconda.syslog tar: Removendo `/ 'principal dos nomes dos membros /var/log/anaconda.program.log tar: Removendo `/ 'principal dos nomes dos membros /var/log/anaconda.storage.log
De uma forma simples, qual é a diferença entre os dois seguintes?
find var/log
e find /var/log
find
comando, você deve citar o termo da pesquisa. Funciona sem às vezes, mas nem sempre.{} +
, em vez de{} \;
ele irá resultados do grupo de achado em um argumentoRespostas:
Nota: Veja a resposta de @ Iain para uma solução um pouco mais eficiente.
Observe que
find
chamará a-exec
ação para cada arquivo que encontrar.Se você executar
tar -cvf file.tar {}
para cadafind
saída de arquivo , isso significa que você será substituídofile.tar
sempre, o que explica por que você acaba com um arquivo que contém apenasanaconda.storage.log
- são as últimasfind
saídas de arquivo .Agora, você realmente deseja anexar os arquivos ao arquivo morto em vez de criá-lo sempre (é o que a
-c
opção faz). Então, use o seguinte:A
-r
opção anexa ao arquivo morto em vez de recriá-lo sempre.Nota: Substitua
-iname anaconda.*
por-iname "anaconda.*"
. O asterisco é um curinga e pode ser expandido pelo seu shell antesfind
mesmo de vê-lo. Para impedir essa expansão, coloque o argumento entre aspas duplas.Quanto à
tar
remoção dos principais/
: O arquivo deve conter apenas nomes de arquivos relativos . Se você incluísse arquivos à esquerda/
, eles seriam armazenados como nomes absolutos , literalmente/var/…
no seu computador, por exemplo.IIRC: isso é simplesmente uma precaução para
tar
implementações diferentes do GNU, e é mais seguro dessa maneira, porque você não substituirá seus dados reais/var/…
quando extrair o arquivo, se ele contiver nomes de arquivos relativos.fonte
tar
um arquivo de fita real dessa maneira, adicionando um arquivo de cada vez, rebobinando a fita e relendo a coisa toda a cada vez para chegar ao fim, tudo seria ridiculamente lento. Sua solução é adequada apenas se você estiver gravando o arquivo tar no disco.find /var/log/ -iname anaconda*
dando nada efind /var/log/ -iname anaconda.*
dando a saída, por quê?find
. Portanto, se você tiveranaconda*
, e na sua pasta atual houver algo chamado, por exemplo,anaconda5
(correspondente a este curinga), o curinga será expandido efind
será exibido em-iname anaconda5
vez de-iname anaconda*
. Por que o primeiro não funciona e o segundo depende de quais arquivos estão no diretório atual. @max{} +
vez de,{} \;
para que ele agrupe os resultados da busca em um argumentoVocê pode usar algo como:
O
-print0
e-T
trabalham juntos para permitir que nomes de arquivos com espaços novas linhas, etc. A final-
diz tar a ler os nomes dos arquivos de entrada de stdin.Observe que
-print0
deve aparecer no final de sua declaração, de acordo com esta resposta . Caso contrário, você provavelmente obterá mais arquivos do que espera.fonte
-name
opção, causando sua solução paratar
todo o diretório. Se é isso que você deseja, você pode fazê-lo mais facilmente,tar -cvf file.tar var/log
sem usarfind
.tar
é uma boa ideia. Definitivamente, é a melhor solução se você espera que os nomes de caminho possam ter espaços. Eu o descreveria como o melhor tecnicamente, pois é confiável e eficiente. Mas requer conhecimento especial adicional de ambosfind
etar
. Prefiro a substituição de comandos apenas porque é uma ferramenta mais geral: aprenda a usá-lo uma vez e depois em qualquer lugar. (Mas admito, estou no Windows com um shell onde sempre funciona.) Desculpas se parecesse rude.xargs
.-print0
opção find , também precisa da--null
opção tar .--no-unquote
acaba sendo necessário também: nomes de arquivos contendo barras invertidas seriam manipulados incorretamente. (Não, este não é um hipotético - Estou realmente criar um arquivo tar de outra pessoa código, contendo um nome de arquivo com barras invertidas no nome, é assim que eu descobri.)Tente o seguinte:
Você estava tentando usar
find
a-exec tar
. Mas, da maneira que a-exec
opção funciona, ele executa esse comando uma vez para cada arquivo correspondente encontrado, fazendotar
com que sobrescreva o arquivo tar que ele produz a cada vez. É por isso que você acabou com o último. Além disso, você precisa colocar aspas no padrão especificado parafind
que o shell não o expanda antes de passá-lo parafind
.Usando substituição de comando com reticulares (ou usando
$(...)
notação, se você preferir), toda a lista de nomes produzidos porfind
é colada de volta na linha de comando como argumentos paratar
, fazendo com que ela escreva todos de uma vez.fonte
find
raramente é uma boa idéia. mywiki.wooledge.org/ParsingLsread -r
de-print0
) como fiz na minha resposta.Questão 1
Seu comando falha porque
tar
está pegando cada um dos arquivos encontrados e arquivando-osfile.tar
. Sempre que fizer isso, ele substituirá o criado anteriormentefile.tar
.Se o que você deseja é um arquivo com todos os arquivos, basta executar
tar
diretamente, não há necessidadefind
(e sim, isso funciona para arquivos com espaços em seus nomes):Questão 2
Os dois comandos são completamente diferentes:
O comando find var / log procurará em um diretório chamado
var/log
subdiretório do diretório atual , é equivalente afind ./var/log
(observe o./
).O find / var / log pesquisará um diretório chamado
/var/log
subdiretório da raiz/
,.A
/
mensagem principal é detar
, nãofind
. Isso significa que ele está removendo o primeiro nome/
de arquivo para transformar caminhos absolutos em relativos . Isso significa que o arquivo/var/log/anaconda.error
será extraído para./var/log/anaconda.error
quando você descompactar o arquivo morto.fonte
Existem duas maneiras de
-exec
funcionar. Uma maneira de executar o comando várias vezes - uma vez para cada arquivo; por outro lado, executa o comando uma vez, incluindo todos os arquivos como uma lista de parâmetros.-exec tar -cvf file.tar {} ';'
executa otar
comando para cada arquivo, substituindo o arquivo cada vez.-exec tar -cvf file.tar {} '+'
executa otar
comando uma vez, criando um arquivo morto de todos os arquivos encontrados.fonte
Eu acho que usar -exec para cada arquivo pode tornar a compactação do tar muito lenta, se você tiver muitos arquivos. Eu prefiro usar o comando:
fonte
/bin/cpio: xxx: Cannot open: Too many open files