Вот мой вариант использования: утилита командной строки melt
может принять имя файла с расширением .melt
в командной строке и открыть его; в качестве примера, вот правильный test_p.melt
файл:
colour:blue
out=24
colour:red
out=48
... который открывается и воспроизводится с melt test_p.melt
.
Теперь, дело в том, что .melt
файлы не поддерживают комментарии, хотя я бы хотел, чтобы они это делали (вы получите сообщения об ошибках для любой строки, содержащей неанализируемый аргумент, включая те, которые содержат, скажем, a #
). Итак, вот закомментированный test_c.melt
файл:
# master comment here
colour:blue # this is blue!
out=24
colour:red
out=48
Открытие этого melt
напрямую дает:
$ melt test_c.melt
Failed to load "# master comment here"
...
... и никакого синего экрана не отображается.
Поэтому я подумал - ну, я могу оставить комментарийв любом случае, а затем использовать подстановку процесса Bash для фильтрации файла с помощью sed
, и просто предоставить это приложению melt
. Сначала попробовал тест с cat
, который прошел успешно:
$ cat <(sed 's/#.*$//' test_c.melt)
colour:blue
out=24
colour:red
out=48
... выглядит неплохо;но, если я попробую это с melt
, он раскроет мой обман:
$ melt <(sed 's/#.*$//' test_c.melt)
Failed to load "/dev/fd/62"
Failed to load "/dev/fd/62"
По сути, melt получил имя файла канала, предоставленного Bash для подстановки процесса, но, к сожалению, melt
он обрабатывает его argv[i]
напрямую; в случае файла ему необходимо увидеть .melt
расширение в имени файла; если его нет, процесс завершается ошибкой.
Итак, мой вопрос: как я могу использовать подстановку процесса - так, чтобы имя файла канала имело определенное расширение, в этом случае .melt
? По сути, в результате подстановки я хотел бы получить имя файла канала /dev/fd/62.melt
, что, я думаю, пройдет.
Примечание: конечно, я всегда могу сделать:
sed 's/#.*$//' test_c.melt > test_c_temp.melt
melt test_c_temp.melt
... но, во-первых, здесь две команды, а мне бы хотелось конвейер из одной строки; а во-вторых, это создает еще одну проблему, связанную с необходимостью впоследствии удалять временные файлы, что мне не нравится.
Возможно ли это с помощью подстановки процессов Bash или каким-то образом с помощью стандартных инструментов Linux?
решение1
Одним из вариантов было бы указание melt
на файловую систему, которая показывает измененные копии файлов.ПРЕДОХРАНИТЕЛЬэто универсальный способ создания драйвера файловой системы, реализуемый обычной программой и не требующий привилегий. Естьмножество файловых систем FUSE вокруг, и есть хороший шанс, что один из них может вам помочь. Идея заключается в том, чтобы предоставить точку монтирования, где чтение файла .melt
считывает «реальный» файл, но с отфильтрованными комментариями.
ScriptFSвыглядит многообещающе (но я никогда этим не пользовался). Что-то вроде этого должно работать:
mkdir ~/uncommented-melt
scriptfs -p "$HOME/bin/uncomment-melt;&*.melt" ~/work ~/uncommented-melt
где ~/work
находится корень дерева, содержащего ваши .melt
файлы ~/bin/uncomment-melt
и
#!/bin/sh
sed 's/#.*$//' "$1"
Затем, если у вас есть файл ~/work/test_c.melt
с комментариями, вы можете запустить melt ~/uncommented-melt/test_c.melt
.
Другие потенциально полезные файловые системы FUSE:
решение2
С помощью zsh
оболочки вы можете использовать =(...)
форму подстановки процессов (которая использует временные файлы вместо /dev/fd/x
файлов и каналов), для которой вы можете указать суффикс:
(TMPSUFFIX=.melt; melt =(sed 's/#.*$//' test_c.melt))
Подробную информацию см . в разделе info zsh TMPSUFFIX
(если info
страницы установлены, возможно, вам потребуется установить пакет).zsh-doc
решение3
Хорошо, оказывается, что в моем конкретном случае такие сценарии melt должны интерпретироваться строго как аргументы командной строки; поэтому одного sed
в OP недостаточно (плюс, есть и другие вещи, например профили, которые можно задать). Итак, вот что я в итоге сделал — вероятно, это может послужить вдохновением в других случаях, которые будут охвачены названием OP.
В конце концов я остановился на следующем: создайте test.shmelt
файл, который на самом деле является bash
скриптом, содержащим мой прокомментированный melt
код скрипта; сделайте этот файл исполняемым chmod +x test.shmelt
; затем после редактирования скрипта запустите его как ./test.shmelt
.
При запуске он создаст "очищенный" test.melt
файл в /tmp
и вызовет melt
этот файл вместо него. Так как melt
обычно продолжает работать в терминале после завершения своей программы, с ловушкой на SIGINT этот временный файл может быть очищен при нажатии Ctrl-C (но не обязательно).
Таким образом, у меня по-прежнему будут комментарии, я смогу быстро редактировать исходный файл, запускать Melt и видеть результаты, а также иметь файл, «очищенный» от комментариев, который я смогу использовать позже.
Вот код test.shmelt
:
#!/bin/bash
# call with: ./test.shmelt
#TMLTFILE="test.melt" # for final export
TMLTFILE="${0%%.shmelt}.melt" # for final export
function finished() { echo ; } ; # use this when testing or montaging to keep exported (tmp) .melt file; uncomment the below to remove the tmp file
#~ function finished() { rm /tmp/"$TMLTFILE"; echo "fin1 $0" ; } ; trap finished SIGINT ;
echo 'Remember `pulseaudio --start` to hear audio with `melt`!'
pulseaudio --check
if [ $? -ne 0 ]; then
pulseaudio --start
fi
DIRNAME=$(readlink -f $(dirname $0))
PROFILE="square_ntsc"
echo "
# the profile doesn't work from here;
# still has to be specified on command line
# but including it here so the path is saved for testing
#~ -profile
#~ ${PROFILE}
-video-track
# can avoid pixmap: here, but that s the producer;
# qimage: also works
# NB it is NOT '-out 1645'; but 'out=1645'!!
/media/myimg/%05d.bmp
in=0
out=1645
#~ length=1645
#~ loop=0
#~ eof=stop
-audio-track
/media/mysnd/snd.wav
in=0
out=1645
#~ loop=0
#~ eof=stop
#-consumer xml # doesn't work here
" | sed -e 's/#.*$//' -e 's/^[[:space:]]*//' -e '/^[[:space:]]*$/d' -e 's/[[:blank:]]*$//' > ${TMLTFILE}
# the sed: remove comments; remove indents; remove empty lines; remove spaces at end of line
# eof: one of: stop, loop, continue or pause (eof=stop)
# to loop, use `melt eof=loop ...` (but make sure first,
# that the edit as a whole stops - use xml to check!)
# due to caching issues, preview pieces (up to ~300 frames) like this:
melt eof=loop -profile ${PROFILE} ${TMLTFILE} in=200 out=400
# must have profile here, for checking w/ -consumer xml (else segfault)
# this command may add additional producers to the xml!:
## melt -profile ${PROFILE} ${TMLTFILE} -consumer xml
# use this to generate xml if needed:
#melt -profile ${PROFILE} $(cat ${TMLTFILE} | tr '\n' ' ') -consumer xml
# if exited normally, cleanup:
finished
решение4
Прошло много времени, но я постараюсь ответить на вопрос заголовка так, чтобы это было полезно для меня.
Это связано:Почему подстановка процессов BASH не работает с некоторыми командами?
Итак, конкретная проблема, которую я пытался решить, была следующей:
- У меня есть конвертер изображений;
- он конвертирует из [вставьте случайный формат] в простые форматы, такие как BMP/PNM/TGA;
- Я хочу конвертировать в JPEG, поэтому мне нужно связать это с ImageMagick
convert
; - Я не хочу использовать временные файлы.
Итак, к сожалению, инструмент не любит выводить в stdout/fds/pipes, потому что он выводит формат вывода из расширения имени выходного файла. Так как же его обмануть?
Создайте символическую ссылку с соответствующим расширением /dev/fd/N
и используйте ее как «временный файл».
Пример:
ln -s /dev/fd/4 temp.pnm
[TOOL] -i [INPUTFILE] -o temp.pnm 4>&1 | convert - [OUTPUT.JPG]