loop com cat

Iniciado por sigur, 15 de Fevereiro de 2012, 20:37

tópico anterior - próximo tópico

sigur

Pessoal, tenho file1, ..., filen na pasta. São arquivos de texto.

Quero colocar o conteúdo deles em um só, como se fosse colado um após o outro.

Tentei usar o seguinte:
cat file* >> saida
mas não deu certo, pois ficou assim:
file1
file1 + file2
...
file1 + ... + filen
ou seja, ele fez uma série e não uma sequência, isto é, o conteúdo dos arquivos ficaram repetidos.

Como fazer? Não queria ter que fazer n vezes
cat file1 >> saida && file2 >> saida


irtigor

Use um laço

for i in file*; do
   [[ -f $i ]] || continue
   cat "$i" >> saida
done

sigur

Citação de: irtigor online 15 de Fevereiro de 2012, 21:38
Use um laço

for i in file*; do
   [[ -f $i ]] || continue
   cat "$i" >> saida
done


Opa, valeu hein! Posso digitar isso tudo no terminal, dando <enter> só no final, uma vez só?
Ou isso só funciona com um file.sh?

|| é um OU lógico, não é? Então, o que faz o [[ -f $i ]] ?

irtigor

Um teste: http://aurelio.net/shell/canivete/#test

Olhando de novo o exemplo, eu vejo que o problema são os arquivos, então use

for i in file*; do
   [[ -f $i ]] || continue
   cat "$i" >> saida && echo -n "\n" >> saida
done


E pode copiar e colar, direto... mas certifique-se que está no diretório correto.

sigur

Certo, para cada arquivo, ele testa se o arquivo existe. se sim, faz o cat. só não entendi o porque de usar o || continue. seria para garantir que se o arquivo não existe, então ele tenta com o próximo? mas esse laço não é exatamente para o file*, ou seja, sempre terá o arquivo. A menos que não tenha nenhum arquivo file?

Outra coisa, para que serve a opção -n do echo? sei que o \n é para inserir newline, mas o -n como opção?

irtigor

Se não for um arquivo comum ele pula pro próximo do glob. Com o -n o echo não insere o terminador que indica nova linha. Se você usar vai intender:

echo "inicio" > file1 && echo "meio" > file2 && echo "fim" > file3
cat file*


echo -n "inicio" > file1 && echo -n "meio" > file2 && echo -n "fim" > file3
cat file*


Obs: teste, teste e teste!

sigur

haha, entendi. bacana!
mas pelo que me parece, você usa -n para não ter nova linha, mas depois insere o \n na raça? porque não deixa então sem o -n e sem o \n? vou fazer alguns outros testes. valeu!

irtigor

#7
Porque o arquivo não tem o terminador... veja a diferença:


rm saida &> /dev/null
echo -n "inicio" > file1 && echo -n "meio" > file2 && echo -n "fim" > file3
for i in file*; do
  [[ -f $i ]] || continue
  cat "$i" >> saida && echo -n "\n" >> saida
done
cat saida



rm saida &> /dev/null
echo -n "inicio" > file1 && echo -n "meio" > file2 && echo -n "fim" > file3
for i in file*; do
  [[ -f $i ]] || continue
  cat "$i" >> saida && echo "\n" >> saida
done
cat saida


São arquivos feitos no windows? Compensa mais converter com o dos2unix (pra ter os terminadores corretos) e depois usar o cat com glob normal.

---
Não sei se a minha sugestão anterior vai funcionar, se os arquivos tiverem mais de uma linha, porque a nova linha só é inserida no final do arquivo.