Я использую bash, чтобы получить некоторую информацию из audacious в conky для отображения (включая обложку альбома). Я получаю путь к каталогу музыкального файла из audacious, затем пытаюсь перейти в этот каталог, чтобы найти folder.jpg - если он найден, подготовиться к отображению. К сожалению, нельзя полагаться на "правильно сформированные" имена путей. Ни у одного из них нет проблем с терминалом, но оценки, которые делает bash... Он подавляется двойными пробелами ( ) ' / и, возможно, другими, хотя текущая настройка, похоже, справляется - нормально. Вот соответствующая функция:
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
}
Есть идеи, или будет проще достать проволочную щетку и удалить ржавчину с моего компилятора «C»?
Я пробовал использовать двойные кавычки, одинарные кавычки, обратные кавычки и даже такую конструкцию:
code=$code \"\$filename\""
но пока ничего не работает правильно. К счастью, это не работает 'красиво', потому что вместо этого выскакивает картинка-заменитель "не могу найти обложку", но иногда что-то рыгает по всему stderr до следующей песни или альбома.
решение1
Вы можете использовать file_path="${file_path/#~/$HOME}"
для расширениятолько.~
Насколько я могу судить,расширение тильдыявляется единственным типом расширения, которое необходимо выполнить для вывода audtool --current-song-tuple-data file-path
. Более того, появляется только один конкретный случай нотации тильды: если путь, используемый Audacious, начинается с домашнего каталога пользователя, запустившего Audacious, эта часть пути заменяется на в ~
выводе audtool
. Посколькуaudacious
иaudtool
man-страницы не разъясняют этого, я пытался добраться audtool
до выходных путей, префиксированных формой ~username
раскрытия тильды, и к счастью, похоже, что даже этого не происходит. Я говорю «к счастью», потому что это означает, что ситуация довольно проста.
Поскольку единственное преобразование, которое необходимо выполнить в выходных данных этой audtool
команды, — это заменить лидирующий путь ~
на путь к домашнему каталогу пользователя, вы можете просто написать код в своем скрипте, который сам выполняет это расширение, а в противном случае оставляет путь неизмененным. Вы обнаружили, что имена файлов аудиофайлов, которые вы можете воспроизводить, могут содержать символы, обрабатываемые оболочкой особым образом, иесли вы воспроизводите файлы, названные другими людьми,может даже привести к уязвимости системы безопасностив вашем сценарии. Не позволяя оболочке выполнять (или даже расширять) произвольный, ненадежный текст, вы полностью избегаете этой проблемы.
Есть несколько способов расширить ~
себя. Я предлагаю:
file_path="$(audtool --current-song-tuple-data file-path)" # might need tilde expansion
file_path="${file_path/#~/$HOME}" # do the tilde expansion, if needed
Это вручную выполняет одно преобразование, которое может потребоваться. В частности, когда вывод audtool
начинается с ~
, он заменяется на домашний каталог пользователя, полученный путем проверки значения переменной HOME
. Когда вывод не начинается с ~
, расширение не выполняется.
Обратите внимание, что этот подход, ${file_path/#~/$HOME}
, будетнетбыло бы правильным, если бы оно использовалось как попытка симулировать все формы расширения тильды, поскольку оно выполняло бы неверные подстановки в форме ~username
(и в некоторых других, более неясных формах). Однако, пока пути в выводе audtool
используют только обозначение тильды в простом случае обозначения домашнего каталога текущего пользователя — что, как я полагаю, имеет место — тогда этот подходявляетсяуместно и правильно для этих путей.
Вот как это работает:
- В общем,Баш будет расширяться
${parameter/pattern/string}
в значениеparameter
, но счасть, которая соответствуетpattern
заменено на . Если ни одна часть не соответствует шаблону, используетсяstring
точное значение .parameter
- Если
pattern
написано с ведущим#
, его можно сопоставить только с самого начала значенияparameter
. (Кроме того, есть и другие символы#
, которые имеют значение в этой позиции: a%
потребует, чтобы шаблон сопоставлялся с самого началаконец, а a/
приведет к тому, что шаблон будет сопоставлен и заменен столько раз, сколько он появляется, а не максимум один раз.) ~
не имеет особого значения в шаблоне и поэтому рассматривается буквально, как символ, подлежащий сопоставлению и замене.
Видетьрасширение параметрадля получения подробной информации.
Обратите внимание, что написанный мной код не делает ничего для обработки случая audtool
создания пустого вывода, как это происходит, когда в данный момент не воспроизводится песня (или, какСаймон Садлер упомянул, если есть ошибка). Однако он не прерывается на пустом выводе и не мешает последующей обработке. Так что если вы хотите охватить этот случай, вы все еще можете это сделать.
Наконец, я должен упомянуть, что я упустил из виду два различия, которые, по моему мнению, не имеют значения для вашего варианта использования:
- Поскольку
audtool
пути взяты из Audacious, если бы вы попытались создать странную ситуацию, запустив Audacious от имени одного пользователя, а затемaudtool
от имени другого (и каким-то образом настроили D-Bus так, чтобы это работало), то вам пришлось бы позаботиться о~
ссылке на домашний каталог другого пользователя, нежели пользователь, запустивший скрипт. - Технически говоря, расширение тильды для текущего пользователя (которое происходит в оболочке само
~
по себе или сразу после него/
) не являетсядовольноэквивалентно"$HOME"
. Оболочки могут попытаться обработать странный случай, когдаHOME
не установлено. Bash пытается обработать это и все равно выдать правильное расширение. Я сомневаюсь, что вас волнует различие для этой цели. См.расширение тильдыдля получения подробной информации.
решение2
Переназначение переменных file_path
не обязательно. Есть 2 признака того, что может произойти, что может нарушить скрипт:
- Переменная пуста, так как
audtool
возвращается ошибка - Возвращает
audtools
каталог, содержащий пробелы. audtool
включает в себя~
для домашнего каталога
Вот предложение о том, как решить эти проблемы:
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
}
Обрабатывает "$(command)"
пробелы в имени папки (если они есть). Не используйте cd
внутри скрипта, если вам это не нужно. Проверка того, является ли возвращаемая строка каталогом, всегда хорошая идея. Работа с абсолютным путем в большинстве случаев лучше и предотвращает выполнение команд в неправильной папке.
Примечания к ~
расширению в bash:
Расширение ~
обрабатывается bash, поэтому readlink -f
здесь не поможет. Поэтому переменная, содержащая , ~
должна быть выполнена без кавычек, чтобы быть расширенной (я обновил скрипт). Конечно, это можно сделать в одной строке...
# 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