Estou usando o bash para obter algumas informações de audacioso a conky para exibição (incluindo a arte do álbum). Eu obtenho o caminho para o diretório do arquivo de música do audacious e, em seguida, tento fazer um cd para esse diretório para encontrar a pasta.jpg - se encontrado, prepare-se para exibição. Infelizmente, não podemos confiar em nomes de caminhos 'bem formados'. Nenhum deles tem problemas no terminal, mas as avaliações que o bash tem ... Ele engasga com espaços duplos ( ) ' / e provavelmente outros, embora a configuração atual pareça funcionar - ok. Aqui está a função relevante:
GetArt ()
{
file_path=`audtool --current-song-tuple-data file-path` # get the path to the song
file_path=$(eval echo "${file_path}") # pre-expand to full path
cd "${file_path}"
if [[ ! -e "folder.jpg" ]]; # if no art work found
then
cp ~/Work/vinyl.png /tmp/cover.png # put in placeholder
else
convert "${file_path}""/folder.jpg" -resize 120x120 /tmp/cover.png # ready for showing
fi
}
Alguma idéia, ou seria mais fácil pegar a escova de aço e remover a ferrugem do meu compilador 'C'?
Tentei com aspas duplas, aspas simples, crases e até uma construção como:
code=$code \"\$filename\""
mas nada parece funcionar corretamente ainda. Felizmente, ele falha 'muito' porque apenas aparece a foto substituta "não consigo encontrar arte", mas às vezes as coisas arrotam por todo o stderr até a próxima música - ou álbum.
Responder1
Você pode usar file_path="${file_path/#~/$HOME}"
para expandirapenaso ~
.
Tanto quanto posso dizer,expansão de tilé o único tipo de expansão que precisa ser executada na saída de audtool --current-song-tuple-data file-path
. Além disso, apenas um caso específico de notação de til aparece: se o caminho que o Audacious está usando começar com o diretório inicial do usuário que está executando o Audacious, essa parte do caminho será substituída por um ~
na saída de audtool
. Desde oaudacious
eaudtool
as páginas de manual não esclarecem isso, tentei chegar audtool
aos caminhos de saída prefixados com a ~username
forma de expansão do til e, felizmente, parece que nunca consegui fazer isso. Digo “felizmente” porque isso significa que a situação é bastante simples.
Como a única transformação que precisa ser feita na saída desse audtool
comando é substituir um início ~
pelo caminho do diretório inicial do usuário, você pode simplesmente escrever um código em seu script que faça essa expansão sozinho e, caso contrário, deixe o caminho inalterado . Você descobriu que os nomes dos arquivos de áudio que você pode reproduzir podem conter caracteres tratados especialmente pelo shell ese você reproduzir arquivos nomeados por outras pessoas,pode até dar origem a uma vulnerabilidade de segurançano seu roteiro. Ao não fazer com que o shell execute - ou mesmo expanda - texto arbitrário e não confiável, você evita esse problema completamente.
Existem várias maneiras de ~
se expandir. Eu sugiro:
file_path="$(audtool --current-song-tuple-data file-path)" # might need tilde expansion
file_path="${file_path/#~/$HOME}" # do the tilde expansion, if needed
Isso executa manualmente a única transformação que pode ser necessária. Especificamente, quando a saída de audtool
começa com ~
, isso a substitui pelo diretório inicial do usuário, obtido pela verificação do valor da HOME
variável. Quando a saída não começa com ~
, nenhuma expansão é executada.
Observe que esta abordagem, ${file_path/#~/$HOME}
, serianãoestaria correto se fosse usado como uma tentativa de simular todas as formas de expansão do til, porque realizaria substituições incorretas no ~username
formulário (e em algumas das outras formas mais obscuras). No entanto, desde que os caminhos na saída audtool
usem apenas a notação til no caso simples de designar o diretório inicial do usuário atual - o que acredito ser o caso - então esta abordageméapropriado e correto para esses caminhos.
A maneira como funciona é:
- Em geral,Bash irá expandir
${parameter/pattern/string}
no valor deparameter
, mas coma parte que combinapattern
substituído porstring
. Se nenhuma peça corresponder ao padrão, o valor exato deparameter
será usado. - Quando
pattern
é escrito com um início#
, ele só pode ser correspondido começando no início do valor deparameter
. (Existem outros caracteres além#
dos que são significativos nesta posição: a%
exigiria que o padrão fosse correspondido no própriofim, e a/
faria com que o padrão fosse correspondido e substituído quantas vezes aparecesse, em vez de no máximo uma vez.) ~
não tem nenhum significado especial em um padrão e, portanto, é tratado literalmente, como um caractere a ser combinado e substituído.
Verexpansão de parâmetrospara detalhes.
Observe que o código que escrevi não faz nada para lidar com o caso de audtool
produção de saída vazia, como acontece quando não há nenhuma música tocando no momento (ou, comoSimon Sudler mencionou, se houver um erro). No entanto, ele não quebra na saída vazia nem atrapalha o manuseio subsequente dela. Então, se você quiser cobrir esse caso, ainda pode.
Por fim, devo mencionar que encobri duas distinções que acredito não serem importantes para o seu caso de uso:
- Como
audtool
os caminhos do Audacious vêm do Audacious, se você estivesse tentando a situação bizarra de executar o Audacious como um usuário eaudtool
como outro - e de alguma forma configurou o D-Bus para que funcionasse - então você teria que se preocupar em~
se referir a um diferente diretório inicial do usuário do que o usuário que está executando o script. - Tecnicamente falando, a expansão do til para o usuário atual (que acontece em um shell sozinho
~
ou seguida imediatamente por/
) não ébastanteequivalente a"$HOME"
. Os shells podem tentar lidar com o caso estranho ondeHOME
não está definido. Bash tenta lidar com isso e ainda produzir uma expansão correta. Duvido que você se importe com a distinção para esse propósito. Verexpansão de tilpara detalhes.
Responder2
A reatribuição das file_path
variáveis não é necessária. Existem 2 sinais que podem acontecer, que podem quebrar o script:
- A variável está vazia porque
audtool
retorna um erro - O
audtools
retorna um diretório, que contém espaços em branco. audtool
inclui~
para o diretório inicial
Aqui está uma proposta sobre como abordar essas questões:
GetArt ()
{
file_path="$(audtool --current-song-tuple-data file-path)"
file_path="$(readlink -f "$(bash -c "echo $file_path")")"
if [[ ! -d $file_path ]]; then
echo "error: $file_path does not exists"
exit 1
fi
folder_jpg="$file_path/folder.jpg"
if [[ ! -e "$folder_jpg" ]]; then
cp ~/Work/vinyl.png /tmp/cover.png
else
convert "$folder_jpg" -resize 120x120 /tmp/cover.png
fi
}
Manipula "$(command)"
os espaços em branco no nome da pasta (se houver). Não use cd
dentro de um script, se não precisar dele. Verificar se a string de retorno é um diretório é sempre uma boa ideia. Trabalhar com o caminho absoluto é, na maioria dos casos, melhor e evita a execução de comandos na pasta errada.
Notas para a ~
expansão no bash:
A expansão do ~
é feita pelo bash, então readlink -f
não ajuda aqui. Portanto, a variável que contém ~
deve ser executada sem aspas para ser expandida (atualizei o script). É claro que isso pode ser tratado em uma única linha ...
# expansion from current bash
$ set -x; readlink -f ~; set +x
+ readlink -f /home/user
/home/user
+ set +x
# expansion will not work, with quoted ~
$ set -x; readlink -f '~'; set +x
+ readlink -f '~'
/home/user/~
+ set +x
# expansion from un-quoted ~ with sub-shell
$ set -x; readlink -f "$(bash -c "echo ~")"; set +x
++ bash -c 'echo ~'
+ readlink -f /home/user
/home/user
+ set +x