Estou tentando compactar todos os arquivos no ubuntu com extensão de arquivo .css, .html ou .js. em um diretório superior e em todos os subdiretórios. Desejo manter os arquivos originais e substituir o arquivo .gz, se já existir.
Portanto, quando tenho n arquivos, quero mantê-los e criar n arquivos adicionais. Não é só um.
Minha tentativa foi executar um script que se parece com isso:
gzip -rkf *.css
gzip -rkf *.html
... one line for each file extension
Primeiro: preciso ter uma linha nesse script para cada extensão de arquivo que eu quero compactar. Tudo bem, mas espero encontrar uma maneira melhor
Segundo e mais importante: não funciona. Embora -r deva fazer o trabalho, os subdiretórios não são alterados. O arquivo gzip é criado apenas no diretório superior.
O que estou perdendo aqui?
Btw: A seguir, há um erro na saída detalhada, certo? Ao usar a opção -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. Enfim, isso é 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
-r
funciona como projetado. No man gzip : Percorra a estrutura de diretórios recursivamente. Se qualquer um dos nomes de arquivos especificados na linha de comando forem diretórios , o gzip descerá para o diretório e compactará todos os arquivos que encontrar lá (ou descompactá-los no caso do gunzip). (ênfase meu)Respostas:
você pode fazer isso com um loop for para encontrar todos os arquivos e compactá-los:
fonte
-r
opção não funcione-k
e-f
esteja funcionando, eu posso usá-las assim: para i infind | grep -E "\.css$|\.html$"
; faça gzip -vkf "$ i"; done` #`...`
fornece uma string, não uma lista.for
usa o separador de campo interno ($IFS
) para decidir onde essa sequência deve ser dividida. Por padrão, ela se divide em Linefeeds, tabulações e espaços, por isso, se você tem um arquivo chamadonew style.css
, os comandosgzip new
egzip style.css
será executado.export IFS=$'\n'
imediatamente antes dofor
loop.eu usaria
Altere
name
parainame
se você deseja corresponder as extensões sem distinção entre maiúsculas e minúsculas (por exemplo, incluir.CSS
e / ou.HTML
extensões). Você pode omitir o/path/to/dir
se desejar iniciar a pesquisa recursiva no diretório atual.fonte
--keep
opção, sim, isso faz com que os arquivos originais sejam mantidos. Omita-o se quiser que eles sejam excluídos depois de compactados com gzip.Para obter a lista de arquivos:
E para compactar todos esses arquivos:
fonte
tar
a lista de arquivos como saídafind
, em vez dos próprios arquivos?-T
opçãotar
processa a entrada como nomes de arquivos.Eu usei a resposta de steeldriver , mas eu gosto de completá-lo com o
--best
e--force
opções.cd
em qualquer pasta e digite este código. Todos os seus arquivos correspondentes serão compactados em gzip.--best
para a melhor taxa de compactação.--force
para substituir sem perguntar se já existe um arquivo compactado em gzip.fonte
Você pode usar globstar.
Com a
globstar
opção de shell ativada, tudo que você precisa égzip -vk **/*.{css,html}
.O shell Bash tem uma
globstar
opção que permite que você escreva recursiva globs com**
.shopt -s globstar
permite. Mas você pode não querer fazer isso para outros comandos executados posteriormente, para que você possa executá-lo e seugzip
comando em uma subshell .Este comando
gzip
é tudo.css
e.html
arquivos no diretório atual qualquer de seus subdiretórios, qualquer um de seus subdiretórios, etc., mantendo os arquivos originais (-k
) e dizendo-lhe o que está fazendo (-v
):Se você deseja corresponder os nomes dos arquivos sem distinção entre maiúsculas e minúsculas, para que aquelas extensões com algumas ou todas as letras maiúsculas sejam incluídas, também é possível ativar a
nocaseglob
opção shell:;
separa os dois comandos e o externo(
)
faz com que eles sejam executados em um subshell. Definir uma opção de shell em um subshell não faz com que ela seja definida no shell de chamada. Se você não deseja ativarglobstar
, em seguida, você pode executarshopt -s globstar
; então você pode simplesmente executar o comando:Você pode desativar
globstar
comshopt -u globstar
. Você pode verificar se está ativado no momentoshopt globstar
.Como funciona
A chave de como esse
gzip
comando funciona é que o shell execute expansões nele para produzir uma lista de cada arquivo na hierarquia de diretórios com um nome correspondente e, em seguida, transmita cada um desses nomes de arquivo como argumentos paragzip
.**/*.{css,html}
transforma**/*.css **/*.html
.**
devido aglobstar
) cujos nomes de arquivos consistem em qualquer coisa (*
) seguida pelo sufixo especificado (.css
ou.html
neste caso).Isso não corresponde aos arquivos cujos nomes começam com
.
ou aos que residem nos diretórios nomeados dessa maneira. Você provavelmente não possui esses arquivos HTML e CSS e, se tiver, provavelmente não deseja incluí-los. Mas se você quiser incluí-los, poderá correspondê-los explicitamente, dependendo de suas necessidades. Por exemplo, alterar**/*.{css,html}
para**/{,.}*.{css,html}
inclui arquivos que começam com.
ainda não pesquisam nas pastas que o fazem.Se você deseja que os arquivos cujos nomes começam com
.
e os diretórios cujos nomes começam.
sejam incluídos, existe uma maneira mais limpa e simples: habilite adotglob
opção shell.Ou se você deseja correspondência que não diferencia maiúsculas de minúsculas e correspondência de nomes de arquivos que começam com
.
:É possível, embora muito raro,
**
expandir para algo muito longo.Se você tiver um grande número de arquivos nomeados dessa maneira, isso poderá falhar com uma mensagem de erro explicando que o shell não pode criar a linha de comando porque seria muito longo. (Mesmo com milhares de arquivos, isso geralmente não é um problema.)
gzip
não será chamado, então você não terá um trabalho pela metade.Se esse erro ocorrer, ou se você estiver preocupado com isso, poderá usá-lo
find
com-exec
, como a steeldriver descreve (com{} \;
) ou como eu descrevo abaixo (com{} +
).Você pode usar
find
com a-exec
ação e+
obter eficiência.O
gzip
comando suporta receber nomes de vários arquivos a serem compactados. Mas estefind
comando, embora funcione bem e não seja lento, a menos que você tenha muitos arquivos, executa ogzip
comando uma vez para cada arquivo:Isso funciona e você pode definitivamente usá-lo. (
.
pesquisa no diretório atual. Além disso, é realmente uma maneira ligeiramente diferente de escrever o comando na resposta muito boa do steeldriver ; você pode usar o estilo que preferir.)Você também pode
find
passar vários nomes de arquivos paragzip
e executá-lo apenas quantas vezes forem necessárias - o que é quase sempre apenas uma vez. Para fazer isso, use em+
vez de\;
. O+
argumento deve vir logo depois{}
.find
substitui+
por nomes de arquivos adicionais, se houver.É bom usá-lo
+
mesmo se houver apenas alguns arquivos correspondentes e, quando houver muitos deles, poderá ser visivelmente mais rápido do que ter umagzip
chamada separada para cada arquivo.Como a steeldriver menciona , é possível usar, em
-iname
vez de,-name
para corresponder aos arquivos cujo nome termina como.css
ou.html
mas com letras maiúsculas diferentes. Isso corresponde à habilitaçãonocaseglob
noglobstar
método baseado em descrito acima.Finalmente, você provavelmente não possui nenhum arquivo ou diretório correspondente que comece com
.
. Mas se você o fizer,find
inclui-os automaticamente. Se você deseja excluí- los (como acontece com oglobstar
método baseado em detalhes detalhado acima quandodotglob
desativado), você pode :A
globstar
maneira baseada em descrita acima é mais simples de escrever, especialmente se você estiver excluindo diretórios e arquivos que começam com.
, pois esse é o padrão.O que não fazer ...
Os nomes de arquivos podem conter qualquer caractere, exceto o separador de caminho
/
e o caractere nulo . Existem muitas técnicas que quebram em nomes de arquivos estranhos, e geralmente são mais complicadas do que técnicas que sempre funcionam. Então, sugiro evitá-los, mesmo quando você sabe (ou pensa que sabe) que eles estão bem em sua situação específica. E, é claro, você não deve usá-los se tiver nomes de arquivos com caracteres que possam ser tratados especialmente, incluindo espaços.É possível canalizar com segurança a saída
find
para outro comando que a processa se você usar-print0
uma ação semelhante para fazer com que ele coloque um caractere nulo entre os caminhos, em vez de uma nova linha , e não o contrário. Os nomes de arquivos podem conter novas linhas (embora eu o desencoraje de nomear arquivos deliberadamente com eles). Umfind
comando com a-print
ação - incluindo comandos find sem ação explícita, desde então-print
é o padrão - não produz saída que possa ser canalizada com segurança ou fornecida de outro modo a outro comando que executa uma ação nos arquivos.A saída
find
produzida com a-print0
ação pode ser canalizada com segurançaxargs -0
(o-0
sinalizador indicaxargs
para esperar uma entrada separada por nulo).fonte
Para compactar todos os arquivos em uma pasta / subpasta recursivamente:
Para descompactar:
fonte
`
`
a sintaxe, mas o problema se aplica plenamente ao usar a$(
)
sintaxe também.)