Category Archives: bash

Como remover espaço em branco do nome de arquivos

Aqui uma dica de como renomear uma lista de arquivos que contém espaço em branco no nome, substituindo o espaço por underscore. Apresento duas soluções, uma para Korn shell e outra para Bash.

Em Korn shell pode-se usar o comando sed:

Continue reading Como remover espaço em branco do nome de arquivos

Incrementar variável numérica em bash2

Até a bash 1, para você incrementar uma variável numérica de 1 em 1 era preciso toda uma contorção:

contador=0; \
while [ $contador -lt 10 ]; \
do echo "o valor do contador eh $contador"; \
let contador=$contador+1; \
done

Agora, com a bash2, você pode usar o for de maneira parecida com a sintaxe do C:

for (( contador=0; contador < 10; contador++ )); \
do echo "o valor do contador eh $contador" ;\
done

bash: Argument list too long

Pode ser que você já tenha tentado dar um comando usando o asterisco * na bash e tenha obtido este erro:

bash: comando: Argument list too long

Aonde comando pode ser um rm, ou um cp, ou qualquer outro. Por exemplo:

[email protected]:~/teste$ rm -f *
bash: /bin/rm: Argument list too long
[email protected]:~/teste$

Quem imprimiu esse erro não foi o comando (o rm, no exemplo), mas a bash, que é responsável por expandir o wildcard *, substituindo-o pela lista de arquivos no diretório. Em sistemas UNIX, há um limite fixo de memória reservado para o ambiente e lista de parâmetros de um comando. No caso do meu servidor Linux, esse limite é 128K, mas isso varia de sistema para sistema. Você pode descobrir no seu sistema usando o comando getconf. Veja:

[email protected]:~/teste$ getconf ARG_MAX
131072
[email protected]:~/teste$

Agora, ao que interessa. Como fazer para remover os arquivos do meu exemplo acima? Existem diversas saídas, variando a eficiência dependendo de qual é o seu comando, na verdade. Mas vamos ver o rm, pois o exemplo dele pode ser aplicado a outros, como por exemplo o cp, ou o mv.

Se você puder eliminar o diretório inteiro no qual estão os arquivos, não há problemas:

[email protected]:~$ rm -rf teste/
[email protected]:~$

Se você só pode eliminar os arquivos, uma saída é usar o comando find.

[email protected]:~/teste$ find . -type f -exec rm -f {} \;
[email protected]:~/teste$

Nesse caso, eu pedi para o find encontrar no diretório em que estou (.) todos os arquivos (-type f) e para cada um deles executar (-exec) o comando rm. As chaves {} são substituídas por cada arquivo encontrado pelo find. Dessa forma o rm é executado uma vez para cada arquivo, tendo assim apenas aquele arquivo como parâmetro, o que evita ultrapassar o limite de memória imposto. O final \; é para fechar o comando do -exec com um ponto e vírgula, que precisa ser precedido da contra barra (\) para que a bash não o interprete (uma vez que ; é um caractere com sentido especial para a bash) e apenas o passe para o find.

Caso, por exemplo, você precise remover somente os arquivos html e não os arquivos .php em um diretório, basta usar o find novamente:

[email protected]:~/teste$ ls *.php
1.php  2.php
[email protected]:~/teste$ ls
(saida resumida:)
23497.html  36998.html  50498.html  6399.html   774.html    9.html
23498.html  36999.html  50499.html  639.html    77500.html
23499.html  3699.html   5049.html   63.html     77501.html
2349.html   369.html    504.html    64000.html  77502.html
234.html    36.html     50500.html  64001.html  77503.html

[email protected]:~/teste$ find . -name \*.html -exec rm -f {} \;
[email protected]:~/teste$ ls
1.php  2.php
[email protected]:~/lixo

Aqui o asterisco funciona porque está precedido pela contrabarra o que faz com que a bash não o interprete, apenas o find. E find não expande o asterisco em todos os arquivos do diretório, como a bash. Para o find, o asterisco é parte de uma expressão regular, que quer dizer “encontre arquivos cujo nome seja qualquer coisa seguida de um .html”.

Eu uso a versão da GNU do find, presente na maioria dos sistemas Linux. Caso o seu find não entenda o parâmetro -exec, use-o em conjunto com comando xargs:

[email protected]:~/teste$ find . -name \*.html | xargs rm -f
[email protected]:~/teste$ ls
1.php  2.php
[email protected]:~/teste$

Referências:

http://www.gnu.org/software/coreutils/faq/coreutils-faq.html#Argument-list-too-long