Passando argumentos com espaços e aspas para um script (sem citar tudo)

2

O seguinte funciona muito bem na linha de comando:

$ ffmpeg -i input.m4a -metadata 'title=Spaces and $pecial char'\''s' output.m4a

Como parametrizar esse comando e usá-lo em um script / função? Gostaria de adicionar várias tags de metadados assim:

$ set-tags.sh -metadata 'tag1=a b c' -metadata 'tag2=1 2 3'

update:

Eu simplifiquei minha pergunta um pouco demais. Eu realmente quero chamar um script que chame um script com o comando parametrizado nele.

Este é o meu caso de uso exato:

Esta função converte arquivos em formato de livro de áudio (definido em .profile):

# snippet of .profile
convert_to_m4b () {
    FILE="$1"
    BASENAME=${FILE%.*}; shift

    ffmpeg -i "$FILE" -vn -ac 1 -ar 22050 -b:a 32k "$@" tmp.m4a &&
    mv tmp.m4a "$BASENAME.m4b"
}; export -f convert_to_m4b

A função convert_to_m4b é chamada de download-and-convert.sh:

#/bin/sh
 MP3_URL=$1; shift
FILENAME=$1; shift

if [ ! -f "${FILENAME}.mp3" ]; then
    curl --location --output "${FILENAME}.mp3" "$MP3_URL"
fi

convert_to_m4b "${FILENAME}.mp3" "$@"

Download-and-convert.sh é chamado de process-all.sh:

#/bin/sh
download-and-convert.sh http://1.mp3 'file 1' -metadata 'title=title 1' -metadata 'album=album 1'
download-and-convert.sh http://2.mp3 'file 2' -metadata 'title=title 2' -metadata 'album=album 2'
...
...
download-and-convert.sh http://3.mp3 'file N' -metadata 'title=title N' -metadata 'album=album N'

Eu recebo este erro do ffmpeg:

[NULL @ 00000000028fafa0] Unable to find a suitable output format for ''@''
'@': Invalid argument

"$@" funciona se eu inline convert_to_m4b em download-and-convert.sh em vez de chamar a função.

O seguinte não funciona porque as aspas são perdidas, fazendo com que os argumentos com espaços sejam divididos incorretamente:

#/bin/sh
ffmpeg -i input.m4a $@ output.m4a

Eu tentei vários métodos de citando o $@ , mas isso acaba também citando '-metadata' , então o argumento da linha de comando não é reconhecido corretamente.

Eu acho que gostaria de apenas cercar cada argumento com aspas se esse argumento fosse citado para começar. Isso parece difícil de fazer porque o bash retira as aspas antes de passar argumentos para o script / função.

Ou existe um método melhor de retransmitir os argumentos -metadata ? (como variáveis de ambiente ou arquivos)

    
por Leftium 06.09.2017 / 07:20

1 resposta

4

"$@" faz exatamente o que você deseja, desde que você a use consistentemente. Aqui está uma pequena experiência para você:

  • script1.sh :

    #! /bin/sh
    ./script2.sh "$@"
    
  • script2.sh :

    #! /bin/sh
    ./script3.sh "$@"
    
  • script3.sh :

    #! /bin/sh
    printf '|%s|\n' "$@"
    

Com isso, os argumentos não ficam incomodados até o fim:

$ ./script1.sh -i input.m4a -metadata "title=Spaces and \$pecial char's" output.m4a
|-i|
|input.m4a|
|-metadata|
|title=Spaces and $pecial char's|
|output.m4a|
    
por 06.09.2017 / 08:15