loop com for - modelos de script com for

Atualizado em: 25/07/2006



Sobre este documento

Modelos de script com uso do for.

loop com arquivos

Aplicar comandos em todos arquivos do diretório corrente.

Segue alguns modelos para aplicar comandos em todos arquivos do diretório corrente.

Escolha a condição que melhor lhe atende, o script, executará os comandos uma vez para cada arquivo da condição que se encontrar dentro do diretório, neste exemplo abaixo, condição de pesquisa é (*.txt), sobre eles é executado um (echo $1), o resultado é mostrar todos os .txt do diretório corrente, funciona como um ls, veja os demais exemplos e modifique a seu modo.

  #!/bin/bash
  for i in *.txt ; do
    #coloque aqui seus comandos
    echo $i
  done

Este exemplo não parece inútil, serve somente como exemplo de script, troque "echo $i" para a aplicação que deseja, segue alguns exemplos, converter todos os textos para o formato MSDOS bastou trocar "echo $i" por "unix2dos $i"

  #!/bin/bash
  for i in *.txt ; do
    #coloque aqui seus comandos
    unix2dos $i
  done

Ler arquivo linha por linha, troque o echo pelo comando desejado, o exemplo abaixo quebra a linha nos espaços e acaba exibindo palavra por linha, isto ocorre porque o espaço ou TAB é o delimitador default, como não foi informado outro o delimitador o espaço serviu como quebra de linha, veja o exemplo posterior com a correção.

  for i in `cat /tmp/arquivo.txt`
  do
     # seus comandos aqui
      echo $i
  done

Corrigindo o problema, alterando o delimitador para usar o final de linha, observe que altera o IFS para $'\n e no final volta o que era.

  ORI_IFS=$IFS
  IFS=$'\n'
  for LINHA in $(cat /tmp/testez/comandos.txt); do
     # seus comandos aqui
      echo $LINHA
  done
  IFS=$ORI_IFS

O script acima exibe a linha completa mas elimina as linhas em branco, com while no script abaixo exibe a linha completa inclusive as linhas em branco como estão no arquivo.

  while read LINHA ; do
     # seus comandos aqui
      echo $LINHA
  done < /tmp/testez/comandos.txt

Para exibir linha por linha de uma arquivo o cat faz isto,

cat /tmp/testez/comandos.txt

os scripts com for e while acima servem como modelo para incluir comandos em lugar do echo..

sed -n 1p /tmp/testez/comandos.txt

cat /tmp/testez/comandos.txt | awk '{ print $0}'

converter páginas do manual (man) para arquivos em html.

  #!/bin/bash
  for i in *.gz ; do
    #coloque aqui seus comandos
    man ./$i | man2html -title man\ $i -topm 5 > $i.html
  done

No exemplo acima acrescenta requer o pacote man2html instalado, acrescenta .html no nome do arquivo, find.1.gz em html fica find.1.gz.html, a "gambi" do exemplo abaixo mantém somente a parte do nome antes do primeiro ponto, find.1.gz em html tem o nome find.html.

  #!/bin/bash
  for i in *.gz ; do
    #coloque aqui seus comandos
    nome=`basename $i .1.gz`
    man ./$i | man2html -title man\ $nome -topm 5 > $nome.html
  done

Falhou em man2 porque tem páginas do man em man1, man2, man3 até man6, o exemplo acima não funcionou como desejado porque falha nos demais diretórios, a solução "gabi" abaixo pega somente a parte do nome que vem antes do primeiro ponto.

  #!/bin/bash
  for i in *.gz ; do
    #coloque aqui seus comandos
    arqespac=`echo $i | sed 's:\.: :g'`
    nome=`echo $arqespac | awk '{print $1}'`
    echo $nome
    man ./$i | man2html -title man\ $nome -topm 5 > $nome.html
  done

Como pode notar nos exemplos acima, pode acrescentar linhas até obter o resultado desejado, pode tentar tudo em uma única linha ou usar script para realizar tarefas por parte, com arquivos grande pode tornar a tarefa demorada, tudo é questão de testar e procurar pela ferramenta mais apropriada.

Parte de um script de backup, veja script com mais detalhes nos tutoriais sobre backup. Em /backup/dirhome.txt tem a lista de diretórios, cada linha no formato /home/diretorio o script abaixo monta a linha de comando do tar nomeando o arquivo com homediretorio.meiodia.tar.gz, uma linha de comando para cada linha do arquivo, monta e executa uma por uma

  for i in `cat /backup/dirhome.txt`
  do
    #coloque aqui seus comandos
    MVAR2=`echo $i | sed "s|/||g"`
    /bin/tar czf $MVAR2.meiodia.tar.gz $i
  done

varios comandos sed

Loop com for, executar uma sequencia de comandos nos arquivos listados em arqlista, não use ponto ou caracteres especiais no nome deste arquivo, execute o script dentro do diretório onde estão os arquivos a serem modificados, este script é uma versão simplificada para limpar arquivos com download de messagens da lista de shell-script no yahoo, são arquivos pequenos e não tive preocupação com velocidade e outros detalhes, somente remover cabeçalhos e rodapé dos textos, funciona!.

  #!/bin/bash
  for i in $( cat arqlista );do
    # exibir o nome do arquivo sendo processado
     echo $i
    # apagar da linha 1 até a 22
    sed -i '1,22d' "$i"
    # depois apaga a linha 2 e 3
    sed -i '2,3d' "$i"
    # apagar todas as linhas que contem "As partes desta mensagem"
    sed -i '/As partes desta mensagem/Id' "$i"
    # apagar as ultimas 9 linhas
    sed -i -e :a -e '$d;N;2,9ba' -e 'P;D' "$i"
  done

Exibir o nome do arquivo sendo processado, acrescente esta linha

echo $i

Ela vai exibir o parametro que o sed deverá usar. Ou se preferir, modifique a linha de comando do sed para exibir o conteúdo que casa com a condição, por exemplo retirar o -i ou trocar "d" por "!p", ou "p" algo como:

sed '1,22d' "$i"

Executar o script, basta criar o arquivo acima, faça a correção dos comandos e condição para o teu uso, torne executável e execute

chmod 777 arqlista sh arqlista

Outra versão do script acima com redirecionamento da saida.

Versões mais antigas do sed não tem a opçõa -i, precisa redirecionar a saida para outro arquivo e depois renomear, também em casos de aplicar outros comandos que requer o redirecionamento, nunca esqueça da copia de segurança, preferencialmente para outro local, ou melhor, pratique na cópia. No exemplo abaixo é feita a copia no mesmo diretório, como se aplica o sed varias varias, então precisa fazer a copia e renomear em cada aplicação do sed.

  #!/bin/bash
  for i in $( cat arqlista );do
    # exibir o nome do arquivo sendo processado
     echo $i
    # apagar da linha 1 até a 22
    mv "$i" arqtemp
    sed '1,22d' arqtemp > "$i"
    rm arqtemp
  done

until

Uso do until é identico ao while, procure por until no manual (man bash)

Formato de uso until

  until [ condição verdadeira ] ; do
    # comandos
  done

Exemplo de script com until, fique atento à condição.

  #!/bin/bash
  i=5
  until [ $i -le 0 ] ; do
    # seus comandos aqui.
    echo "numero do contador atual $i"
    i=$[$i-1]
  done

Indicações

Veja também sobre uso de watch e tail, no tutorial sobre log tem exemplos.

FAQ com respostas na lista Linux-br
http://www.zago.eti.br/script/loop.txt

sed em loop for - mais exemplos de loop
http://www.zago.eti.br/script/sed.html

while - exemplos de loop
http://www.zago.eti.br/script/while.html

Diversos modelos de scripts com uso de: for, while, until
http://www.linux.com/guides/abs-guide/loops1.shtml

Página principal sobre script em geral (FAQ)
http://www.zago.eti.br/script/A-menu-scripts.html

Página principal deste site (FAQ)
http://www.zago.eti.br/menu.html