Ler arquivo e executar ação para cada linha [RESOLVIDO]

1. Ler arquivo e executar ação para cada linha [RESOLVIDO]

Joao Vitorino
Joao_Vitorino

(usa Red Hat)

Enviado em 24/09/2013 - 15:36h

Boa tarde galera.

Preciso de ajuda pra criar um script.
1º meu problema: tenho uma lista de arquivos que tenho que mover de uma pasta para outra ( essa lista costuma ter entre 60 e 200 arquivos)
2º o que faço: Atualmente identifico um padrão no nome desses arquivos e uso wildcards para me ajudar a fazer na mão ( exemplo: mv ????algumacoisa*.algumacoisa)

Queria uma script para facilitar isso, criaria um arquivo (exemplo lista_arquivos) com a lista dos arquivos a serem movidos e ao executar o script pediria para que lesse o lista_arquivos e para cada linha ele movesse o arquivo encontrado.

Um detalhe, ainda tenho que verificar a existência dos arquivos da pasta (dizer quais arquivos da lista não estavam na pasta de origem).

Sei que paro isso tenho que usar algo como for ou while mas não entendo direito dessas coisas ( não ainda)


  


2. MELHOR RESPOSTA

Paulo
paulo1205

(usa Ubuntu)

Enviado em 24/09/2013 - 16:08h

Vão sugerir-lhe que use algo como vai abaixo.

for arq in `cat lista_arquivos`; do
processa $arq
done


Eu, porém, recomendo não usar essa forma porque ela faz com que o shell leve todo o conteúdo do arquivo lista_arquivos para a memória, para depois usar um de cada vez através da variável arq. O problema com isso é que se o conteúdo da lista for muito grande, o consumo de memória pode impactar o sistema (certamente não será o seu caso com 200 arquivos, mas se você acostumar a usar somente essa construção, no dia em que aparecer uma lista gigantesca, você pode ter problemas).

Eu prefiro e recomendo sempre que se use uma outra forma (abaixo), que, ao custo de um descritor de acesso a arquivo, não consome mais memória do que o tamanho de cada linha, mesmo que o arquivo contenha uma quantidade imensa de linhas.

exec 3< lista_arquivos  # associa lista_arquivos ao descritor 3

while read arq <&3; do # Lê uma linha de cada vez do descritor 3.
processa "$arq" # note as aspas: são importantes se o nome do arquivo contiver espacos,
# acentos ou outros caracteres potencialmente problemáticos.
done

exec 3<&- # libera descritor 3


Na hora de associar ou desassociar um descritor, é bom lembrar que 0, 1 e 2 são normalmente associados ao terminal, de modo que você deve começar a usar descritores livres começando em 3.

Se, em lugar de uma lista fixa, você tiver de ler a saída de outro programa, pode usar uma construção parecida.


exec 3< <(script_gerador_da_lista) # Note o espaço entre os dois sinais "<".
# O script será executado, não lido. A saída da
# execução é que vai para o descritor 3.

while read arq <&3; do
processa "$arq"
done

exec 3<&-


3. Funfou. Porém...

Joao Vitorino
Joao_Vitorino

(usa Red Hat)

Enviado em 24/09/2013 - 17:51h

paulo1205 escreveu:

Vão sugerir-lhe que use algo como vai abaixo.

for arq in `cat lista_arquivos`; do
processa $arq
done


Eu, porém, recomendo não usar essa forma porque ela faz com que o shell leve todo o conteúdo do arquivo lista_arquivos para a memória, para depois usar um de cada vez através da variável arq. O problema com isso é que se o conteúdo da lista for muito grande, o consumo de memória pode impactar o sistema (certamente não será o seu caso com 200 arquivos, mas se você acostumar a usar somente essa construção, no dia em que aparecer uma lista gigantesca, você pode ter problemas).

Eu prefiro e recomendo sempre que se use uma outra forma (abaixo), que, ao custo de um descritor de acesso a arquivo, não consome mais memória do que o tamanho de cada linha, mesmo que o arquivo contenha uma quantidade imensa de linhas.

exec 3< lista_arquivos  # associa lista_arquivos ao descritor 3

while read arq <&3; do # Lê uma linha de cada vez do descritor 3.
processa "$arq" # note as aspas: são importantes se o nome do arquivo contiver espacos,
# acentos ou outros caracteres potencialmente problemáticos.
done

exec 3<&- # libera descritor 3


Na hora de associar ou desassociar um descritor, é bom lembrar que 0, 1 e 2 são normalmente associados ao terminal, de modo que você deve começar a usar descritores livres começando em 3.

Se, em lugar de uma lista fixa, você tiver de ler a saída de outro programa, pode usar uma construção parecida.


exec 3< <(script_gerador_da_lista) # Note o espaço entre os dois sinais "<".
# O script será executado, não lido. A saída da
# execução é que vai para o descritor 3.

while read arq <&3; do
processa "$arq"
done

exec 3<&-


Paulo1205, obrigado, funcionou 99%.

Dei uma pesquisada sobre descritores e vi que é bastante útil.

O único problema é que ao executar a ação ( no meu caso mover os arquivos ), é adicionado o caractere "?" no fim de todos os arquivos movidos.




4. Re: Ler arquivo e executar ação para cada linha [RESOLVIDO]

Fernando
phoemur

(usa Debian)

Enviado em 24/09/2013 - 20:29h

Outra alternativa para mover os arquivos é usar o xargs


xargs -L1 -t -i mv -n {} /home/diretorio_destino < arquivo_lista


A opção -L1 é para executar a ação para cada 1 linha do arquivo


5. Re: Ler arquivo e executar ação para cada linha [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 24/09/2013 - 21:59h

akbar415 escreveu:

Paulo1205, obrigado, funcionou 99%.

Dei uma pesquisada sobre descritores e vi que é bastante útil.

O único problema é que ao executar a ação ( no meu caso mover os arquivos ), é adicionado o caractere "?" no fim de todos os arquivos movidos.


Hum...

Como foi gerado o arquivo que contém a lista de arquivos a serem movidos?

Se o arquivo tiver sido gerado com terminação de linha a la Windows, pode ser que apareça um caráter de retorno da cabeça de impressão (carriage return, abreviado como "CR", que ocupa a posição 13 na tabela ASCII). Isso seria porque o Windows usa um par de caracteres para terminar uma linha de texto (CR+LF -- de line feed, que ocupa a posição 10 no ASCII), ao passo que o UNIX usa apenas um caráter (LF).

Se for o caso de convenção de marca de fim de linha, você poderia usar o comando "tr -d\\r" para eliminar os CRs. Aliás, se os arquivos não tiverem nomes exóticos (i.e., que incluam o próprio sinal de quebra de linha, retorno do carro, tabulações etc.), não fará mal chamar o comando mesmo que a convenção de fim de linha seja a do próprio UNIX.

Mas seria interessante você postar aqui seu script, para ver se o caráter a mais não resulta de alguma outra coisa.


6. Re: Ler arquivo e executar ação para cada linha [RESOLVIDO]

Joao Vitorino
Joao_Vitorino

(usa Red Hat)

Enviado em 24/09/2013 - 23:49h

paulo1205 escreveu:


Hum...

Como foi gerado o arquivo que contém a lista de arquivos a serem movidos?

Se o arquivo tiver sido gerado com terminação de linha a la Windows, pode ser que apareça um caráter de retorno da cabeça de impressão (carriage return, abreviado como "CR", que ocupa a posição 13 na tabela ASCII). Isso seria porque o Windows usa um par de caracteres para terminar uma linha de texto (CR+LF -- de line feed, que ocupa a posição 10 no ASCII), ao passo que o UNIX usa apenas um caráter (LF).

Se for o caso de convenção de marca de fim de linha, você poderia usar o comando "tr -d\\r" para eliminar os CRs. Aliás, se os arquivos não tiverem nomes exóticos (i.e., que incluam o próprio sinal de quebra de linha, retorno do carro, tabulações etc.), não fará mal chamar o comando mesmo que a convenção de fim de linha seja a do próprio UNIX.

Mas seria interessante você postar aqui seu script, para ver se o caráter a mais não resulta de alguma outra coisa.


Estou em casa agora e não tenho como postar o script, nas era isso mesmo. Recebo a lista de arquivos por email no Windows, eu estava apenas dando ctrl+c ctrl+v e gerando um arquivo txt no windows. Ai bastou inserir no script uma linha para usar um programa dos2unix no arquivo.
Obrigado pela ajuda pessoal.


7. Resolvido

Joao Vitorino
joao_vitorino

(usa Red Hat)

Enviado em 14/03/2014 - 14:46h

Obrigado pela ajuda pessoal.

Antes de executar o comando, bastou converter o arquivo com o programa dos2unix.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts