Iterar vários parâmetros com espaços no script bash

5

Eu tenho um script bash para o meu RaspberryPi (executando o Raspbian) que deve ter vários nomes de arquivo como parâmetro (s) e jogar um após o outro (usando omxplayer ). A estrutura básica é esta:

#!/bin/bash
for f in ${*}
do
  echo "${f}";
done;

Agora tenho problemas quando os nomes dos arquivos de entrada contêm espaços; em particular, o comportamento parece ser inconsistente. Suponha que temos dois arquivos test a b e test d e no mesmo diretório. Executar acima do script com parâmetros diferentes gera isso:

$ ./test test\ a\ b
test
a
b
$ ./test "test a b"
test
a
b
$ ./test test\ a*
test
a
b
$ ./test "test a*"
test
a*

Mas, curiosamente:

./test "test*"
test a b
test d e

Obviamente, somente esta última variante fornece a saída pretendida. É complicado usar, no entanto, especialmente se você quiser assistir a um único arquivo (o preenchimento de tabulação preencherá todo o nome) ou se um dos nomes de pasta no caminho do arquivo contiver espaços.

O que eu posso fazer de diferente no shellscript para que ele sempre se comporte como pretendido? Em particular, ambos de

$./test test*
$./test test\ a\ b test\ d\ e

deve produzir o mesmo resultado

test a b
test d e    

para que o script possa ser usado facilmente usando a conclusão normal da guia.

    
por Raphael 10.02.2013 / 19:01

2 respostas

8

Use "$@" em vez de ${*} (consulte Parâmetros especiais no manual)

for f in "$@"; do 
    echo make sure you quote your "$variables" everywhere in the loop

Há uma abreviação (e mais portátil) para isso:

for f do ...

for f; do também funcionaria em alguns shells, mas não é padrão.

    
por 10.02.2013 / 19:19
1

Uma maneira alternativa é usar um loop while de duas maneiras:

input_cmd|while read i; do
  echo "$i";
done

ou através da substituição de processos:

while read i; do
  echo "$i";
done < <(input_cmd)

O último é um bashismo até onde eu sei, então ele pode não funcionar em outros shells compatíveis com o bourne.

Já que você está obtendo a entrada da linha de comando, pode ser melhor ficar com a solução de loop for oferecida na resposta anterior, no entanto.

Você também deve dar uma olhada em man xargs , porque essa é geralmente a melhor maneira de lidar com argumentos exóticos de linha de comando.

    
por 10.02.2013 / 22:48