Enviado em 23/04/2018 - 22:42h 
		mazinatti escreveu:
Bem, eu acho Perl tranquilo porque em muito ele lembra outra ferramentas comuns, como se fosse uma mistura de shell, awk, grep e sed.  De todo modo, a escolha cabe a você, obviamente.
Permita-me fazer alguns comentários no seu código.
#!/bin/bash  
Na verdade, o que você faz nas linhas cima é colocar uma linha em branco e cada um desses arquivos.  Se seu objetivo é remover conteúdo anterior, troque o comando 
echo  pelo comando 
:  (apenas o sinal de “:”, que é um comando que não faz nada), ou não coloque comando nenhum, apenas o redirecionamento.
Isso pode ser problemático se:
  • houver arquivos cujos nomes contenham espaços, tabulações ou quebras de linha;
  • houver muitos arquivos, pois vai consumir muita memória do processo que está rodando o script;
  • não houver nenhum arquivo na forma 
*.txt  (com as configurações mais comuns, isso ocasionaria erro no shell ou por parte de 
ls[ );
  • a lista for vazia (dependeria de preparar o shell para não cair no caso anterior, mas tem seus próprios impactos, especialmente neste seu 
script , conforme discutido mais abaixo).
Não bastassem esses problemas condicionais, você chama 
ls  inutilmente, uma vez que é o próprio shell que expande o padrão “*.txt”.
Seria mais simples e eficiente fazer simplesmente “
lista=( *.txt ) ”, e isso ainda teria o benefício adicional de evitar o problema de arquivos com nomes contendo espaços.  Infelizmente, isso não resolve o gasto de memória provocado por uma eventual lista gigantesca de arquivos (mesmo em princípio preferindo evitar comandos externos, quando eu não necessariamente tenho controle sobre a quantidade de arquivos a ser processada, eu prefiro não trazer toda a lista para a memória de uma só vez, e mais abaixo eu mostrou um jeito de assim fazer).
Para preparar o shell para a possibilidade de não haver nenhum arquivo com sufixo “.txt”, o certo seria executar anteriormente os seguintes comandos (que se aplicam tanto ao uso que você fez de 
ls  quanto à forma alternativa que lhe sugiro).
set +o noglob 
Qual a utilidade desse comando?  Porque o que ele faz é mostrar na saída padrão o conteúdo do primeiro elemento da lista, só que de forma ordenada.  Se você rodar o script no terminal, a saída será na tela.  Tem certeza de que é isso que você quer?
Mas mais problemático ainda é quando o conteúdo de 
lista  é vazio (o terceiro caso da observação anterior).  Nessa situação, o comando 
sort  vai esperar que os dados a serem ordenados venham da entrada padrão.  Se for executado no terminal, o 
script  vai esperar que você digite tal conteúdo.  Tenho quase certeza de que você não quer que isso aconteça.
echo "existem ${#lista} Arquivos em formato *txt na pasta" `ls *.txt`   
Se você já tem a lista, para que rodar novamente o comando 
ls ?  Você poderia conseguir o mesmo efeito com algo como “
echo "..." *.txt ” ou “
echo "... $lista[*]" ”.
Contudo, fica a pergunta: você precisa realmente exibir a lista?
for ((N=0;N<${#lista[*]};N++));do   
Impressão da mensagem à parte, e ignorando a ordenação do primeiro arquivo, que me pareceu um acidente de percurso, uma forma mais segura iterar sobre os elementos da lista de arquivos seria a seguinte.
# Roda o comando find no diretório corrente (.), utilizando um byte nulo como separador 
Dentro do bloco a ser repetido, em lugar de “
${lista[N]} ” você usaria “
"$arquivo" ”.
#faço uma cópia do arquivo original   
Para que essa cópia?  Depois você vai apagá-la, e você não mexe nos arquivos originais.  Assim sendo, você poderia usar os arquivos originais como base para as transformações que quisesse fazer.
#Verifico se o arquivo possui algum conteudo  
Você não deveria ter feito essa verificação antes de copiar o arquivo (supondo que você tenha mesmo de copiá-lo, que não parece ser o caso)?
	    #Aviso com qual arquivo vou trabalhar  
Para os dois primeiros, se o objetivo é somente converte de maiúsculas para minúsculas, em vez de 
awk  você poderia usar 
tr , que é potencialmente mais simples e mais leve.  E não precisaria de dois programas externos (cat ... | awk ...), mas apenas de um deles, como no exemplo abaixo.
Maiuscula=$(tr '[:lower:]' '[:upper:]' < "$arquivo") 
Note que eu coloco “
"$arquivo" ”, com a expansão da variável entre aspas, porque o nome do arquivo pode conter espaços asteriscos e outras coisas perigosas.
Contudo, eu, novamente, desaprovo essa ideia de ler todo o conteúdo para a memória de uma vez só (e triplicado, ainda por cima), porque você pode topar com um arquivo gigantesco, que pode comprometer a execução do seu programa (ou até mesmo do sistema!) ao consumir toda a memória que ele tem disponível.
Seu código de agora é bem diferente do que você mostrou originalmente.  Antes, cada arquivo da lista de arquivos de entrada gerava um arquivo de saída, e cada palavra transformada ocupava um linha distinta nesse arquivo de saída.  Neste de agora, você gera apenas três arquivos, cada um deles contendo uma linha para cada arquivo de entrada, com todas as palavras transformads de cada arquivo numa só linha.
Os dois programas só guardam relação pelas transformações feitas sobre cada palavra, mas a disposição de saída de agora não tem nada a ver com a anterior.  Com essa mudança, qualquer comparação de desempenho em relação ao que se tinha antes fica prejudicada.
Fora isso, como eu sou implicante com a execução de comandos externos desnecessários e com a leitura de todos os dados para a memória de uma vez só (a não ser que haja garantias de que não se vai provocar estouro da memória), eis uma forma de fazer as transformações usando apenas recursos internos do Bash (produzindo saída como a do programa atual, não como o anterior).
# Os três redirecionamentos abaixo podem ficar fora do loop mais externo 
i .  Você não a usa com propósito nenhum no seu programa.find , usado acima.exec 3<&-