gzip todos os arquivos com extensões específicas

9

Eu estou tentando gzip todos os arquivos no Ubuntu que têm a extensão de arquivo .css, .html ou .js. em um diretório principal e em todos os subdiretórios. Eu quero manter os arquivos originais e substituir o arquivo .gz, se já existir.

Então, quando eu tenho n arquivos, eu quero manter esses n arquivos e criar n arquivos adicionais. Não apenas um.

Minha tentativa foi executar um script assim:

gzip -rkf *.css
gzip -rkf *.html
... one line for each file extension

Primeiro: eu preciso ter uma linha nesse script para cada extensão de arquivo que eu quero gzip. Tudo bem, mas espero encontrar uma maneira melhor

Segundo e mais importante: não funciona. Embora -r deva fazer o trabalho, os subdiretórios permanecem inalterados. O arquivo gzip é criado apenas no diretório principal.

O que estou perdendo aqui?

Btw: O seguinte é um bug na saída detalhada, certo? Ao usar as opções -k e -v

-k, --keep        keep (don't delete) input files
-v, --verbose     verbose mode

A saída detalhada diz que substitui o arquivo, embora "substituir" signifique que o arquivo original não existe após a substituição. De qualquer forma, essa é apenas a saída.

$ ls
  index.html      subdir1  testfile      testfile.css.gz
  javaclass.java  subdir2  testfile.css
$ gzip -fkv *.css
  testfile.css:   6.6% -- replaced with testfile.css.gz
$ ls
  index.html      subdir1  testfile      testfile.css.gz
  javaclass.java  subdir2  testfile.css
    
por Sadik 11.07.2014 / 13:58

6 respostas

7

você pode fazer isso com um loop for para encontrar todos os arquivos e depois compactá-lo:

for i in 'find | grep -E "\.css$|\.html$"'; do gzip "$i" ; done
    
por mndo 11.07.2014 / 14:09
11

eu usaria

find /path/to/dir \( -name '*.css' -o -name '*.html' \) -exec gzip --verbose --keep {} \;

Altere name para iname se você quiser corresponder as extensões sem distinção entre maiúsculas e minúsculas (ou seja, incluir .CSS e / ou .HTML extensões). Você pode omitir o /path/to/dir se quiser iniciar a pesquisa recursiva a partir do diretório atual.

    
por steeldriver 11.07.2014 / 14:24
4

Para obter a lista de arquivos:

find -type f | grep -P '\.js|\.html|\.css'

E para compactar todos esses arquivos:

find -type f | grep -P '\.js|\.html|\.css' | tar cvzf archive.gz -T -
    
por chaos 11.07.2014 / 14:11
2

Eu usei a resposta da steeldriver , mas gosto de completá-la com as opções --best e --force .

cd em qualquer pasta e digite este código. Todos os seus arquivos correspondentes serão compactados.

find . \( -name '*.css' -o -name '*.js' \) -exec gzip --verbose --keep --best --force {} \;
  • Use --best para melhor taxa de compactação.
  • Use --force para sobrescrever sem perguntar se já existe um arquivo gzipado.
por azerafati 27.02.2015 / 10:14
1

Você pode usar globstar.

Com a opção globstar habilitada, tudo que você precisa é gzip -vk **/*.{css,html} .

O shell Bash tem uma opção globstar que permite escrever recursivas < href="https://www.gnu.org/software/bash/manual/bash.html#Pattern-Matching"> globs com ** . shopt -s globstar permite isso. Mas você pode não querer fazer isso para outros comandos executados posteriormente, para poder executá-lo e seu comando gzip em um subshell em vez disso.

Este comando gzip s todos os arquivos .css e .html no diretório atual qualquer um de seus subdiretórios, qualquer um dos seus subdiretórios, etc., mantendo os arquivos originais ( -k ) e dizendo o que está fazendo ( -v ):

(shopt -s globstar; gzip -vk **/*.{css,html})

Se você quiser combinar nomes de arquivos sem distinção entre maiúsculas e minúsculas, de modo que essas extensões com algumas ou todas as letras maiúsculas sejam incluídas, você também pode ativar a opção nocaseglob shell:

(shopt -s globstar nocaseglob; gzip -vk **/*.{css,html})

; separa os dois comandos e o% externo co_de% ( faz com que eles sejam executados em um subshell. Definir uma opção de shell em um subshell não faz com que seja definido no shell de chamada. Se você fizer quiser ativar ) , poderá executar globstar ; então você pode simplesmente executar o comando:

gzip -vk **/*.{css,html}

Você pode desativar shopt -s globstar com globstar . Você pode verificar se está atualmente ativado com shopt -u globstar .

Como funciona

A chave para o funcionamento desse comando shopt globstar é que o shell executa expansões nele para produzir uma lista de cada arquivo na hierarquia de diretórios com um nome correspondente e passa cada um desses nomes de arquivos como argumentos para gzip .

  • Expansão de chaves transforma gzip em **/*.{css,html} .
  • Em seguida, globbing expande esses dois padrões para os nomes dos arquivos acessíveis sob o diretório atual ( **/*.css **/*.html , devido a ** ) cujos nomes de arquivos consistem em qualquer coisa ( globstar ) seguido pelo sufixo especificado ( * ou .css neste caso).

Isso não corresponde a arquivos cujos nomes começam com .html ou aqueles que residem em diretórios denominados deste jeito. Você provavelmente não possui arquivos HTML e CSS e, se fizer isso, provavelmente não deseja incluí-los. Mas se você quiser incluí-los, então você pode combiná-los explicitamente, dependendo de suas necessidades. Por exemplo, a alteração de . para **/*.{css,html} inclui arquivos que começam com **/{,.}*.{css,html} , enquanto ainda não pesquisam em pastas que o fazem.

Se você deseja que os dois arquivos cujos nomes começam com . e os arquivos em diretórios cujos nomes começam com . sejam incluídos, há uma maneira mais simples e limpa: ative a opção . shell.

(shopt -s globstar dotglob; gzip -vk **/*.{css,html})

Ou se você quiser corresponder a correspondência e entre maiúsculas e minúsculas de nomes de arquivos que começam com dotglob :

(shopt -s globstar nocaseglob dotglob; gzip -vk **/*.{css,html})

É possível, embora muito raro, que . seja expandido para algo muito longo.

Se você tiver um número enorme de arquivos com esse nome, isso pode falhar com uma mensagem de erro explicando que o shell não pode construir a linha de comando porque seria muito longo. (Mesmo com milhares de arquivos, isso geralmente não é um problema.)

** não será chamado, então você não conseguirá um trabalho pela metade.

Se esse erro acontecer ou se você estiver preocupado, use gzip com find , como O steeldriver descreve (com -exec ) ou como descrevo abaixo (com {} \; ).

Você pode usar {} + com a ação find e -exec para eficiência.

O comando + suporta receber nomes de vários arquivos a serem compactados. Mas esse comando gzip , embora funcione bem e não seja lento, a menos que você tenha muitos arquivos, executa o comando find uma vez para cada arquivo:

find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} \;

Isso funciona, e você pode definitivamente usá-lo. ( gzip procura no diretório atual. Além disso, é realmente uma maneira um pouco diferente de escrever o comando em steeldriver é muito bom responda ; você pode usar qualquer estilo que preferir.)

Você também pode fazer . passar vários nomes de arquivos para find e executá-los somente quantas vezes forem necessárias - o que é quase sempre apenas uma vez. Para isso, use gzip em vez de + . O argumento \; deve vir logo após + . {} substitui find por nomes de arquivos adicionais, se houver.

find . \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +

Não há problema em usar + , mesmo se houver apenas alguns arquivos correspondentes e, quando houver muitos deles, pode ser notavelmente mais rápido do que ter uma chamada + separada para cada arquivo.

Como o referencia o steeldriver , você pode usar gzip em vez de -iname para corresponder arquivos cujo nome termina como -name ou .css mas com capitalização diferente. Isso corresponde à ativação de .html no método nocaseglob , descrito acima.

Por fim, você provavelmente não possui nenhum arquivo ou diretório correspondente que comece com globstar . Mas se você fizer isso, . os incluirá automaticamente. Se você quiser excluir eles (como acontece com o método find -baseded detalhado acima quando globstar está desativado), você pode :

find . -not -path '*/.*' \( -name \*.css -o -name \*.html \) -exec gzip -vk {} +

A maneira dotglob -based descrita acima é mais simples de escrever, especialmente se você estiver excluindo diretórios e arquivos que começam com globstar , já que esse é o padrão.

O que não faz ...

Nomes de arquivo podem conter qualquer caractere, exceto o separador de caminho . e o caractere nulo . Muitas técnicas que quebram em nomes estranhos de arquivos existem, e elas são geralmente mais complicadas do que as técnicas que sempre funcionam. Então eu sugiro evitá-los mesmo quando você sabe (ou acha que sabe) eles estão bem em sua situação específica. E é claro que você deve não usá-los se você tiver nomes de arquivos com caracteres que possam ser tratados especialmente, incluindo espaços.

É possível canalizar com segurança a saída de / para outro comando que a processa se você usar find ou uma ação semelhante para fazer com que coloque um caractere nulo entre os caminhos em vez de uma nova linha , e não o contrário. Nomes de arquivos podem conter novas linhas (embora eu desencoraje você de nomear arquivos deliberadamente com eles). Um comando -print0 com a ação find - incluindo comandos de localização sem ação explícita, desde então -print é o padrão - não produz saída que pode ser canalizada com segurança ou fornecida a outro comando que executa uma ação nos arquivos.

A saída -print produz com a ação find pode ser canalizada com segurança para -print0 (o xargs -0 sinaliza -0 para esperar entrada separada nula).

    
por Eliah Kagan 14.08.2017 / 17:04
0

Para compactar todos os arquivos em uma pasta / subpasta recursivamente:

gzip -r 'find . -type f -name "*.html"' 

Para descompactar:

gunzip -r 'find . -type f -name "*.gz"' 
    
por Naruto_Hokage 15.09.2016 / 21:42

Tags