gzip vários arquivos em diretórios diferentes e copie para o novo diretório

4

Estou trabalhando com vários arquivos localizados em diretórios diferentes que preciso compactar em arquivos .gz individuais. Eu também preciso mover os arquivos compactados para um único diretório, deixando os originais em paz.

Existe uma maneira de fazer isso usando o comando gzip e um arquivo que contém uma lista de todos os caminhos de arquivo dos arquivos que eu quero compactar?

Desculpas se isso é um pouco prolixo ... Sou relativamente novo no Linux e não consigo pensar em uma forma mais eficiente de redigir isso.

    
por David 03.04.2013 / 18:46

2 respostas

4

Assumindo que a lista de arquivos está armazenada em um arquivo chamado filelist (exatamente um caminho de arquivo por linha) e você deseja armazenar os arquivos compactados em zipdir , roteiro alcançará os resultados desejados:

#!/bin/bash

while IFS= read file; do
    gzip -c "$file" > "zipdir/$(basename "$file").gz"
done < filelist

No bash / dash, você também pode converter o acima para um one-liner:

while IFS= read file; do gzip -c "$file" > "zipdir/$(basename "$file").gz"; done < filelist

Em outros shells (por exemplo, tcsh ou zsh)

bash -c 'while IFS= read file; do gzip -c "$file" > "zipdir/$(basename "$file").gz"; done < filelist'

fará o trabalho.

Se o bash não estiver presente, ele pode ser substituído por traço.

Como funciona

  • ... < filelist redireciona o conteúdo de filelist para ... .

  • while IFS= read file; do ... done passa pelas linhas na filelist, armazena o conteúdo da linha atualmente processada na variável arquivo e executa ... .

    IFS= modifica o separador de arquivos interno. Isso é necessário para manipular espaços múltiplos, iniciais e finais corretamente.

  • gzip -c "$file" > "zipdir/$(basename "$file").gz" compactou o arquivo atualmente processado e armazena a saída em um arquivo com o mesmo nome mais uma extensão .gz no diretório zipdir .

    Aqui basename "$file" extrai o nome do arquivo nu do caminho do arquivo.

por 03.04.2013 / 19:42
0

Eu não acho que gzip suporte a leitura de caminhos de um arquivo. A solução alternativa seria colocar todos os arquivos de destino em um arquivo (tar) ou executá-lo várias vezes.

Se o diretório de destino não estiver limitado em relação à capacidade ou velocidade de transferência, uma solução possível seria mover os arquivos antes de compactá-los na pasta de destino, conforme descrito em esta resposta .

Caso contrário, você deve ler um único nome de arquivo por vez, compactando e criando suas pastas conforme você for.

Crie uma estrutura de pastas

TARGET=~/tmp/out

while read line; do 
    dirname "$line" ; 
done < list.txt | sort -u |
xargs -I%  echo mkdir -p "$TARGET/%"

  ## out: ##
  mkdir /home/jaroslav/tmp/out/code/bash 
  mkdir /home/jaroslav/tmp/out/recipes
  mkdir /home/jaroslav/tmp/out/samba
  mkdir /home/jaroslav/tmp/out/wikipedia

Copiar arquivos

while read line; do
   gzip -c "$SOURCE/$line" > "$TARGET/$line.gz"
done < list.txt

Comandos

  • dirname: remove a última parte de um caminho de arquivo, deixando o diretório
  • leia [arg] < file: lê uma linha de cada vez do arquivo e armazena-a na variável shell arg
  • sort -u: remove entradas duplicadas (deixe u nique)
  • xargs -I%: executa um comando (echo ....) uma vez para cada elemento (nome do dir) do canal (|)
  • gzip -c em > out: comprime e escreve para stdout (-c). > redireciona stdin para um arquivo chamado out.
por 03.04.2013 / 20:10