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
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
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
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.
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 -
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 {} \;
--best
para melhor taxa de compactação. --force
para sobrescrever sem perguntar se já existe um arquivo gzipado. 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
.
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
.
gzip
em **/*.{css,html}
. **/*.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})
.
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 {} \;
).
{} +
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.
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).
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"'
Tags gzip