Shell Script: Como usar a expressão em um for?

1

Eu gostaria de usar o comando find em for . Então eu fiz isso:

for logs in 'find $BACKUP_FOLDER -exec ls -la {} \; | awk '{ if ( $8==2011) printf $0"\n" }''; do
// some command here
done;

Mas parece que não está funcionando, então, se eu tentar descobrir como o comando está sendo interpretado, coloco esta linha em sigilo no meu script:

echo "$BACKUP_FOLDER -exec ls -la {} \; | awk { if ( '$8'==2011) printf $0"\n" }";

E o $8 aparece em branco e o \n está em branco também. Isto é o que é impresso no terminal

/company-logs/engine -exec ls -la {} \; | awk { if ( ''==2011) printf /company/scripts/server/backup/sync_backup.shn }

Como posso corrigir isso?

    
por Valter Silva 05.03.2013 / 15:03

1 resposta

3

Sua pergunta

echo "$BACKUP_FOLDER -exec ls -la {} \; | awk { if ( '$8'==2011) printf $0"\n" }";

não exibe nada útil por dois motivos:

  • Para ver o comando como ele seria executado pelo shell, você precisa escapar dos caracteres especiais $ e " com uma barra invertida.

  • $8 é apenas o oitavo argumento de linha de comando para o bash. Para ver com o que o awk poderia substituí-lo, execute este comando:

    find $BACKUP_FOLDER -exec ls -la {} \; | awk '{ if ( $8==2011) printf $0"\n" }'
    

Sua abordagem

Seu loop não funciona, pois printf $0 imprime uma linha inteira de ls -l (contendo permissões, proprietários, data e hora).

Para corrigir isso, você deve eliminar todos os nomes de arquivo, exceto o nu, usando, por exemplo, awk propriamente dito ou cut:

for logs in 'find "$BACKUP_FOLDER" -exec ls -la {} \; | awk '{ if ( $8==2011) print $0 }' | cut -c 43-'; do ... done

Isso criará problemas se houver espaços nos nomes de arquivos. Definir o separador interno de arquivos apenas para nova linha ( IFS=$'\n' no bash) deve ocupar espaços.

Seu problema

Sua abordagem não é muito portátil, já que uma versão diferente de ls ou uma localidade diferente pode alterar os campos.

Para processar todos os arquivos de 2011, em vez de sua abordagem, eu usaria

for logs in $(find "$BACKUP_FOLDER" -exec bash -c '[[ "$(stat -c %y "$0")" =~ ^2011 ]]' {} \; -print); do ... done

ou, se possível,

find "$BACKUP_FOLDER" -exec bash -c '[[ "$(stat -c %y "$0")" =~ ^2011 ]]' {} \; -exec ... \;

Mais uma vez, modificar o IFS deve cuidar de espaços, mas a segunda abordagem será mais confiável.

find substitui {} pelo arquivo atualmente processado e passa como argumento para bash, que pode acessá-lo como $0 .

stat -c %y "$0" mostra o tempo de modificação de $0 e [[ "$(...)" =~ ^2011 ]] verifica se começa com 2011 .

Se isso ocorrer, bash -c '...' retornará true e -print exibirá o nome do arquivo ou -exec executará um comando.

    
por 05.03.2013 / 15:13