Por que nem todos os arquivos são compactados e como melhorar a solução

8

Eu tenho uma pasta com cerca de 20 mil arquivos. Os arquivos são nomeados de acordo com o padrão xy_{\d1,5}_{\d4}\.abc , por exemplo, xy_12345_1234.abc . Eu queria comprimir os primeiros 10K deles usando este comando:

ls | sort -n -k1.4,1.9 | head -n10000 | xargs tar -czf xy_0_10000.tar.gz

no entanto, o arquivo resultante tinha apenas cerca de 2K arquivos dentro.

ls | sort -n -k1.4,1.9 | head -n10000 | wc -l , no entanto, retorna 10000, conforme o esperado.

Parece-me que estou entendendo mal algo básico aqui ...

Estou usando o zsh 5.0.2 no Linux Mint 17.1, o GNU tar 1.27.1

EDITAR:

bifurcar-se como sugerido por @Archemar soa muito plausível, com o fork mais recente sobrescrevendo o arquivo resultante - o arquivo contém a 'cauda' dos arquivos - 7773 para 9999 .

resultado de xargs --show-limit : Your environment variables take up 3973 bytes POSIX upper limit on argument length (this system): 2091131 POSIX smallest allowable upper limit on argument length (all systems): 4096 Maximum length of command we could actually use: 2087158 Size of command buffer we are actually using: 131072

substituir -c por -r ou -u não funcionou no meu caso. A mensagem de erro foi tar: Cannot update compressed archives

usando -r e -u é inválido e falha com tar: You may not specify more than one '-Acdtrux', '--delete' or '--test-label' option

substituir -c por -a parece ser inválido também e falha com o mesmo tar: You must specify one of the '-Acdtrux', '--delete' or '--test-label' options , embora eu não reconheça o problema azf e Acdtrux pareçam disjuntos para mim.

EDIT 2:

-T parece um bom caminho, eu também encontrei um exemplo aqui .

No entanto, quando tento

ls | sort -n -k1.4,1.9 | head -n10000 | tar -czf xy_0_10000.tar.gz -T - i tar: option requires an argument -- 'T'

bem, talvez os nomes dos arquivos não alcancem o alcatrão? Mas parece que eles, porque quando eu executo

ls | sort -n -k1.4,1.9 | head -n10000 | tar --null -czf xy_0_10000.tar.gz -T - i tar: xy_0_.ab\nxy_1_...<the rest of filenames separated by literal \n>...998.ab Cannot stat: File name too long

Então por que o tar não está vendo os nomes dos arquivos?

    
por kostja 22.09.2015 / 16:22

3 respostas

12

você atingiu o limite de xargs?

xargs --show-limit

tente:

  • crie um fictício .tgz file tar czf xy_0_10000.tar.gz /hello/world
  • substitua -czf por -Azf

quando o xarg atinge seu limite, ele irá bifurcar o comando, então o comando que você executou foi

  tar czf xy_0_10000.tar.gz file1 file2 .... file666
  tar czf xy_0_10000.tar.gz file667 file668 ... file1203
  tar czf xy_0_10000.tar.gz file1024 ... file2000

como cada alcatrão ultrapassa o anterior, você deve estar recebendo apenas a última tar c run.

Editar:

1) de acordo com man tar no unbuntu, -a e -r parece equivalente o acréscimo é feito por (qualquer um) -A, --catenate, --concatenate

2) zip (não gzip ) pode ser usado para adicionar arquivo, talvez uma opção gzip faça o truque. (use | xargs zip -qr xy_0_0000.zip , isso resultará em um arquivo zip, não em um .tar.gz)

3) para usar a solução do @ rsanchez
É importante adicionar a opção ao tar de forma adequada, tente

ls | sort -n -k1.4,1.9 | head -n10000 |tar -czf xy_0_10000.tar.gz -T -

onde  - -T - significa a opção de uso -T e usa - como argumento para -T (você pode gerar uma lista de arquivos em /tmp/foo.lst e usar -T /tmp/foo.lst )

    
por 22.09.2015 / 16:41
12

Não há necessidade de xargs . Se você der diretamente à opção tar o -T - , ele lerá os nomes dos arquivos entrada padrão.

Por exemplo:

... | tar -T - -czf xy_0_10000.tar.gz
    
por 22.09.2015 / 19:24
1

Eu quero complementar as duas outras respostas com uma solução zsh , que nem analisa ls , nem precisa xargs . No entanto, não tenho certeza agora, se ele também sofre com a limitação do comprimento da linha de comando.

  1. Defina uma função que gere sua chave de classificação desejada, modificando $REPLY .

    sortkey() { REPLY=${REPLY[4,9]} }
    

    Isso é equivalente ao seu sort -n -k1.4,1.9

  2. Gere uma matriz $files com os nomes dos arquivos classificados com a função acima:

    files=(*(o+sortkey))
    

    Isso é equivalente a ls | sort -n -k1.4,1.9

  3. Retorna os primeiros 10 000 arquivos com

    ${files[0,9999]}
    

    Isso é equivalente a ls | sort -n -k1.4,1.9 | head -n10000

Então, tudo isso deve funcionar:

sortkey() { REPLY=${REPLY[4,9]} }
files=(*(o+sortkey))
tar -czf xy_0_10000.tar.gz ${files[0,9999]}
    
por 22.09.2015 / 21:38