Código funciona no terminal, mas não no script para renomear (manipular nomes de arquivos com espaços)

3

Eu quero aprender mais, então eu tentei script mais do que apenas usando o terminal. Eu sei rename e posso renomear arquivos de imagem com rename 's/ /_/g' *.jpg , mas quando eu escrevo em um script de shell para apontar para um diretório:

DIRECTORY="/foo/bar"

for imgfile in $(find $DIRECTORY -type f -name \*.jpg); do
    echo 'replacing whitespace in' $(basename $imgfile)
    rename -f 's/ /_/g' *.jpg 
done

não funciona e o terminal pega um arquivo (exemplo: 1234 abcd.jpg ) e echo abcd.jpg . Então, onde estou indo errado?

    
por DᴀʀᴛʜVᴀᴅᴇʀ 18.11.2013 / 19:23

1 resposta

4

Espaços em nomes de arquivos são maus.

Eu vejo três problemas com o script.

1) ao fazer o loop for... , você terá dois valores diferentes quando encontrar um arquivo com espaço. ou seja, se você tiver os arquivos "file1 1.jpg" e "file2 2.jpg" e fizer:

for i in $(find . -type f -name \*.jpg); do 
   echo $i
done

Você terá

./file1 
1.jpg
./file2
2.jpg

porque o shell quebra o argumento em espaços. A saída do comando $(find ...) será

./file1 1.jpg 
./file2 2.jpg 

Quais são quatro palavras para o comando for a ser atribuído em $i --- por padrão, o shell trata os espaços e as novas linhas da mesma maneira quando expande.

Você pode contornar isso alterando o char IFS .

Sua primeira linha poderia parecer:

IFS=$'\n' find $DIRECTORY -type f -name \*.jpg | while read -r imgfile; do

2) você está alimentando o loop for com um único nome de arquivo, então você deve dizer:

rename -f 's/ /_/g' "$imgfile"

caso contrário, *.jpg é expandido no diretório atual, e não em $DIRECTORY (e observe as aspas - dado que $imgfile terá espaços).

3) mesmo assim, se $DIRECTORY tiver algum componente de caminho com espaços, a renomeação falhará (haverá diretórios intermediários que não existem).

4) sugestão (mantendo simples):

DIRECTORY="/foo/bar"
cd $DIRECTORY
rename -f 's/ /_/g' *.jpg

não faz o que você quer?

adicionado : meu script (criado há muito tempo, quando não havia rename no Unix), é isso --- ele removerá espaços e tabs em todos os arquivos no diretório atual que os tenham no nome:

# 
ls -1  | grep -E " |\t" | while read i; do
    a='echo $i | tr " \t" "__"'
    mv -v "$i" $a
done

adicionado ++ : este link encontrei pesquisando esta resposta é excelente.

    
por Rmano 18.11.2013 / 19:42