Я использую bash, чтобы получить некоторую информацию от смелых до хитрых для отображения (включая обложки альбомов). Я получаю путь к каталогу музыкального файла от 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 до следующей песни или альбома.
Перераспределение file_path
переменных не требуется. Может произойти два признака, которые могут нарушить работу сценария:
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
Насколько я могу судить, расширение тильды является единственным видом расширения, которое необходимо выполнить на выходе из audtool --current-song-tuple-data file-path
. Кроме того, когда-либо появляется только один конкретный случай обозначения тильды: если путь, который использует Audacious, начинается с домашнего каталога пользователя, запускающего Audacious, эта часть пути заменяется на ~
в выходных данных audtool
. Поскольку справочные страницы audacious
и audtool
не проясняют этого, я попытался заставить 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 %
потребует сопоставления с шаблоном в самом конце , а /
приведет к сопоставлению с шаблоном и заменяется столько раз, сколько кажется, а не чаще, чем один раз.) ~
не имеет особого значения в шаблоне и поэтому трактуется буквально, как символ для сопоставления и замены. Подробнее см. В расширение параметров .
Обратите внимание, что код, который я написал, ничего не делает для обработки случая, когда audtool
выдает пустой вывод, как это происходит, когда в данный момент нет воспроизводимой песни (или, как Саймон Садлер упомянул , если есть ошибка). Однако он не ломается при пустом выводе и не мешает последующей обработке. Так что, если вы хотите раскрыть это дело, вы все равно можете.
Наконец, я должен упомянуть, что я упустил из виду два различия, которые, я считаю, не важны для вашего варианта использования:
audtool
взяты из Audacious, если вы пытались странная ситуация запуска Audacious как одного пользователя и запуска audtool
как другого - и вы каким-то образом настроили D-Bus так, чтобы он работал - тогда вам придется позаботиться о том, чтобы ~
ссылался на домашний каталог другого пользователя, нежели пользователь запуск сценария. ~
само по себе или сразу после /
) не является вполне эквивалентом "$HOME"
. Оболочки могут пытаться обработать странный случай, когда HOME
не установлен. Bash пытается справиться с этим и все еще производит правильное расширение. Я сомневаюсь, что вы заботитесь о различии для этой цели, хотя. Подробнее см. Расширение тильды .