Como verificar a existência de múltiplos arquivos em um diretório e zipar o mesmo

4

Estou enfrentando um problema ao verificar a existência de arquivos que terminam com a mesma sequência / padrão. Os nomes dos arquivos podem ser os seguintes

abs_123.unl
xyz_123.unl

Atualmente, meu código é como abaixo e funciona bem para um único arquivo, mas no caso de haver vários arquivos disponíveis com o mesmo padrão, se a condição falhar

if [ -s $AZWORK/*$PRCSID.unl ]
then
  tar -cvzf $WORK/INET_$PRCSID.unl.gz $WORK/*$PRCSID.unl
fi

aqui $ PRCSID representa os três últimos dígitos do arquivo

Como posso fazer esse script de shell funcionar para vários arquivos?

    
por baludmr 27.06.2015 / 07:09

4 respostas

4

Eu delegaria a "descoberta" e o "dimensionamento" dos arquivos para find :

find "$WORK" -maxdepth 1 -name "*$PRCSID.unl" -type f  ! -size 0 -print0 | \
   xargs -0 --no-run-if-empty tar -cvzf "$WORK/INET_$PRCSID.unl.gz"

Dessa forma, você também pode filtrar todos os subdiretórios que possam ter o padrão "*_123.unl" .

Opções para find :

  • -maxdepth 1 impede a recursão em subdiretórios
  • -name "*$PRCSID.unl" corresponde aos nomes dos arquivos, certifique-se de que ele seja citado para impedir que * seja expandido pelo shell.
  • -type f apenas arquivos
  • ! -size 0 tamanho importa!
  • -print0 imprime os nomes NUL separados, não estritamente necessários aqui, mas seria se os nomes dos arquivos tivessem novas linhas neles, e isso não prejudicaria

Opções / parâmetros para xargs :

  • -0 assume que stdin é separado por NUL (em vez de separado por nova linha)
  • --no-run-if-empty não é executado se nenhum dado for apresentado no stdin (isto é, se o find tiver uma saída)
  • o restante da linha é o comando a ser executado, com os dados do stdin anexados como parâmetros
por 27.06.2015 / 07:22
2

Você poderia simplesmente fazer:

tar -cvzf "$WORK/INET_$PRCSID.unl.gz" "$WORK"/*"$PRCSID.unl"
    
por 27.06.2015 / 09:10
1

Para verificar a existência de arquivos correspondentes a um padrão, você pode fazer algo parecido com

if [ "$(shopt -s nullglob; printf "%s" "$WORK"/*"$PRCSID".unl)" != "" ]
then
    tar -cvzf "$WORK/INET_$PRCSID.unl.gz" "$WORK"/*"$PRCSID".unl
fi

(suponho que você não pretendesse procurar em um só lugar por .unl arquivos e, em seguida, arquive os arquivos de outro lugar.)

shopt -s nullglob faz com que padrões de nome de arquivo sejam "expandidos" para nada quando eles não correspondem nada, então, se não houver arquivos com nomes terminando com 123.unl no diretório de trabalho, o argumento da string "$WORK"/*"$PRCSID".unl desaparece, deixando printf sem nada para imprimir.

Notas:

  • Você pode trazer o shopt -s nullglob para fora da instrução if , por exemplo,
    shopt -s nullglob                        # Maybe elsewhere in the script
       ⋮
    if [ "$(printf "%s" "$WORK"/*"$PRCSID".unl)" != "" ]
    then
        tar -cvzf "$WORK/INET_$PRCSID.unl.gz" "$WORK"/*"$PRCSID".unl
    fi
    se você estiver disposto a ter esse comportamento (a expansão nula de padrões não correspondentes) na verdade, através da execução do script.
  • Você deve sempre citar as variáveis do shell (por exemplo, "$WORK" e "$PRCSID" ) a menos que você tenha uma boa razão para não e você está certo de que sabe o que está fazendo. Você pode fazê-las por partes, citando apenas as variáveis, por exemplo,
    "$WORK"/*"$PRCSID".unl    and    "$WORK"/INET_"$PRCSID".unl.gz
    ou você pode citar palavras inteiras que contêm variáveis, por exemplo,
    "$WORK/"*"$PRCSID.unl"    and    "$WORK/INET_$PRCSID.unl.gz"
    mas note que você não deve fazer "$WORK/*$PRCSID.unl" , porque isso inclui o * entre aspas e, assim, impede que ele aja como um padrão de expansão de nome de arquivo (ou seja, curinga ou glob).
  • Desde o início do seu padrão de nome de arquivo com um nome de diretório que você tem algum controle sobre - especialmente se for um caminho completo (começando com / ) ou você pode pelo menos garantir que não comece com - ) - então provavelmente você está seguro usando echo em vez de printf "%s" ; ou seja,
    if [ "$(shopt -s nullglob; echo "$WORK"/*"$PRCSID".unl)" != "" ]
    then
        tar -cvzf "$WORK/INET_$PRCSID.unl.gz" "$WORK"/*"$PRCSID".unl
    fi
    e, claro, você pode puxar o shopt -s nullglob da declaração if aqui também.

Outra abordagem

Se você tiver um if - then - else (ou pelo menos um if - then ), Por exemplo, para escrever mensagens de status / log / erro, você provavelmente deve usar as opções acima. Mas, se sua única preocupação é executar o comando tar somente se houver arquivo (s) lá, você pode dispensar o if - then e apenas fazer

(shopt -s failglob; tar -cvzf "$WORK/INET_$PRCSID.unl.gz" "$WORK"/*"$PRCSID".unl)

shopt -s failglob significa que, se um comando for tentado com um argumento contendo padrões de nome de arquivo que não correspondem a nada, o comando não é executado . O acima mencionado alcança precisamente o efeito que o código da sua pergunta está tentando alcançar: execute o comando tar se houver arquivos com nomes terminando com 123.unl no diretório de trabalho, e não, se não houver nenhum.

Novamente, você pode separar o comando shopt -s failglob do tar , por exemplo,  

shopt -s failglob                        # Maybe elsewhere in the script
   ⋮
tar -cvzf "$WORK/INET_$PRCSID.unl.gz" "$WORK"/*"$PRCSID".unl
 se você estiver disposto a ter esse comportamento (a não execução de comandos com padrões não correspondentes) em vigor durante a execução do script.     
por 28.06.2015 / 08:54
-1
O comando

find pode encontrar os arquivos necessários para você e, em seguida, executar qualquer comando no resultado da seguinte forma:

find $WORK -name *.unl -exec tar -zcvf $WORK/INET_$PRCSID.unl.gz {} \;
    
por 27.06.2015 / 10:48