Using process substitution to trick programs expecting files, with specific extensions as argument?











up vote
6
down vote

favorite












Here is my use case: the command line utility melt can accept a file name, with the extension .melt on the command line, and open it; as an example, this is a proper test_p.melt file:



colour:blue
out=24

colour:red
out=48


... which opens and plays with melt test_p.melt.



Now, the thing is that .melt files do not support comments, which I wish they did (you'll get error messages for any line that contains an unparsable argument, including those with, say, a #). So here is a commented test_c.melt file:



# master comment here

colour:blue # this is blue!
out=24

colour:red
out=48


Opening this in melt directly gives:



$ melt test_c.melt
Failed to load "# master comment here"
...


... and there is no blue screen shown.



So I thought - well, I can put in comments anyway, and then use Bash process substitution to filter the file with sed, and simply provide that to the melt application. First, tried a test with cat, which is successful:



$ cat <(sed 's/#.*$//' test_c.melt)



colour:blue
out=24

colour:red
out=48


... looks good; but, if I try that with melt, it sees through my trickery:



$ melt <(sed 's/#.*$//' test_c.melt)
Failed to load "/dev/fd/62"
Failed to load "/dev/fd/62"


Basically, melt got the filename of the pipe Bash provided for the process substitution - but unfortunately, what melt does is that it processes argv[i] directly; and in case of a file, it needs to see a .melt extension in the filename; if it doesn't - the process fails.



So my question is: how could I use process substitution - so the filename of the pipe has a specific extension, in this case .melt? Basically, as a result of the substitution, I'd want a pipe filename of /dev/fd/62.melt, which I think will pass.



NB: of course, I can always do:



sed 's/#.*$//' test_c.melt > test_c_temp.melt
melt test_c_temp.melt


... but first, there are two commands here - and I'd want a one-liner pipeline; and for another, it opens up another problem of me thinking about removing temporary files afterwards, which I don't like.



Is this possible with Bash process substitution - or somehow with standard Linux tools?










share|improve this question




















  • 1




    Try melt < <(sed 's/#.*$//' test_c.melt)
    – Costas
    Jan 28 '15 at 21:55










  • Thanks @Costas - tried that, but apparently melt doesn't care about commands piped through stdin, since I get: Usage: melt [options] [producer [name=value]* ]+ and a dump of program options. Cheers!
    – sdaau
    Jan 28 '15 at 22:00






  • 1




    I have to read man melt on behalf of you. "If no files are specified, the compression is applied to the standard input". So sed 's/#.*$//' test_c.melt | melt > result.file can work.
    – Costas
    Jan 28 '15 at 22:07










  • Thanks again, @Costas - unfortunately, that doesn't work either, at least not on my version of melt (MLT melt 0.6.2; "standard input" is not mentioned in this version's man melt), since for that command, again I get Usage: melt [options] [producer [name=value]* ]+ and a dump. Cheers!
    – sdaau
    Jan 28 '15 at 22:10












  • I think you have to read man melt on your machine. If you cannot find answer post in on pastebin.com and post link here.
    – Costas
    Jan 28 '15 at 22:15















up vote
6
down vote

favorite












Here is my use case: the command line utility melt can accept a file name, with the extension .melt on the command line, and open it; as an example, this is a proper test_p.melt file:



colour:blue
out=24

colour:red
out=48


... which opens and plays with melt test_p.melt.



Now, the thing is that .melt files do not support comments, which I wish they did (you'll get error messages for any line that contains an unparsable argument, including those with, say, a #). So here is a commented test_c.melt file:



# master comment here

colour:blue # this is blue!
out=24

colour:red
out=48


Opening this in melt directly gives:



$ melt test_c.melt
Failed to load "# master comment here"
...


... and there is no blue screen shown.



So I thought - well, I can put in comments anyway, and then use Bash process substitution to filter the file with sed, and simply provide that to the melt application. First, tried a test with cat, which is successful:



$ cat <(sed 's/#.*$//' test_c.melt)



colour:blue
out=24

colour:red
out=48


... looks good; but, if I try that with melt, it sees through my trickery:



$ melt <(sed 's/#.*$//' test_c.melt)
Failed to load "/dev/fd/62"
Failed to load "/dev/fd/62"


Basically, melt got the filename of the pipe Bash provided for the process substitution - but unfortunately, what melt does is that it processes argv[i] directly; and in case of a file, it needs to see a .melt extension in the filename; if it doesn't - the process fails.



So my question is: how could I use process substitution - so the filename of the pipe has a specific extension, in this case .melt? Basically, as a result of the substitution, I'd want a pipe filename of /dev/fd/62.melt, which I think will pass.



NB: of course, I can always do:



sed 's/#.*$//' test_c.melt > test_c_temp.melt
melt test_c_temp.melt


... but first, there are two commands here - and I'd want a one-liner pipeline; and for another, it opens up another problem of me thinking about removing temporary files afterwards, which I don't like.



Is this possible with Bash process substitution - or somehow with standard Linux tools?










share|improve this question




















  • 1




    Try melt < <(sed 's/#.*$//' test_c.melt)
    – Costas
    Jan 28 '15 at 21:55










  • Thanks @Costas - tried that, but apparently melt doesn't care about commands piped through stdin, since I get: Usage: melt [options] [producer [name=value]* ]+ and a dump of program options. Cheers!
    – sdaau
    Jan 28 '15 at 22:00






  • 1




    I have to read man melt on behalf of you. "If no files are specified, the compression is applied to the standard input". So sed 's/#.*$//' test_c.melt | melt > result.file can work.
    – Costas
    Jan 28 '15 at 22:07










  • Thanks again, @Costas - unfortunately, that doesn't work either, at least not on my version of melt (MLT melt 0.6.2; "standard input" is not mentioned in this version's man melt), since for that command, again I get Usage: melt [options] [producer [name=value]* ]+ and a dump. Cheers!
    – sdaau
    Jan 28 '15 at 22:10












  • I think you have to read man melt on your machine. If you cannot find answer post in on pastebin.com and post link here.
    – Costas
    Jan 28 '15 at 22:15













up vote
6
down vote

favorite









up vote
6
down vote

favorite











Here is my use case: the command line utility melt can accept a file name, with the extension .melt on the command line, and open it; as an example, this is a proper test_p.melt file:



colour:blue
out=24

colour:red
out=48


... which opens and plays with melt test_p.melt.



Now, the thing is that .melt files do not support comments, which I wish they did (you'll get error messages for any line that contains an unparsable argument, including those with, say, a #). So here is a commented test_c.melt file:



# master comment here

colour:blue # this is blue!
out=24

colour:red
out=48


Opening this in melt directly gives:



$ melt test_c.melt
Failed to load "# master comment here"
...


... and there is no blue screen shown.



So I thought - well, I can put in comments anyway, and then use Bash process substitution to filter the file with sed, and simply provide that to the melt application. First, tried a test with cat, which is successful:



$ cat <(sed 's/#.*$//' test_c.melt)



colour:blue
out=24

colour:red
out=48


... looks good; but, if I try that with melt, it sees through my trickery:



$ melt <(sed 's/#.*$//' test_c.melt)
Failed to load "/dev/fd/62"
Failed to load "/dev/fd/62"


Basically, melt got the filename of the pipe Bash provided for the process substitution - but unfortunately, what melt does is that it processes argv[i] directly; and in case of a file, it needs to see a .melt extension in the filename; if it doesn't - the process fails.



So my question is: how could I use process substitution - so the filename of the pipe has a specific extension, in this case .melt? Basically, as a result of the substitution, I'd want a pipe filename of /dev/fd/62.melt, which I think will pass.



NB: of course, I can always do:



sed 's/#.*$//' test_c.melt > test_c_temp.melt
melt test_c_temp.melt


... but first, there are two commands here - and I'd want a one-liner pipeline; and for another, it opens up another problem of me thinking about removing temporary files afterwards, which I don't like.



Is this possible with Bash process substitution - or somehow with standard Linux tools?










share|improve this question















Here is my use case: the command line utility melt can accept a file name, with the extension .melt on the command line, and open it; as an example, this is a proper test_p.melt file:



colour:blue
out=24

colour:red
out=48


... which opens and plays with melt test_p.melt.



Now, the thing is that .melt files do not support comments, which I wish they did (you'll get error messages for any line that contains an unparsable argument, including those with, say, a #). So here is a commented test_c.melt file:



# master comment here

colour:blue # this is blue!
out=24

colour:red
out=48


Opening this in melt directly gives:



$ melt test_c.melt
Failed to load "# master comment here"
...


... and there is no blue screen shown.



So I thought - well, I can put in comments anyway, and then use Bash process substitution to filter the file with sed, and simply provide that to the melt application. First, tried a test with cat, which is successful:



$ cat <(sed 's/#.*$//' test_c.melt)



colour:blue
out=24

colour:red
out=48


... looks good; but, if I try that with melt, it sees through my trickery:



$ melt <(sed 's/#.*$//' test_c.melt)
Failed to load "/dev/fd/62"
Failed to load "/dev/fd/62"


Basically, melt got the filename of the pipe Bash provided for the process substitution - but unfortunately, what melt does is that it processes argv[i] directly; and in case of a file, it needs to see a .melt extension in the filename; if it doesn't - the process fails.



So my question is: how could I use process substitution - so the filename of the pipe has a specific extension, in this case .melt? Basically, as a result of the substitution, I'd want a pipe filename of /dev/fd/62.melt, which I think will pass.



NB: of course, I can always do:



sed 's/#.*$//' test_c.melt > test_c_temp.melt
melt test_c_temp.melt


... but first, there are two commands here - and I'd want a one-liner pipeline; and for another, it opens up another problem of me thinking about removing temporary files afterwards, which I don't like.



Is this possible with Bash process substitution - or somehow with standard Linux tools?







bash filenames process-substitution






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Apr 7 at 16:57









Jeff Schaller

37k1052121




37k1052121










asked Jan 28 '15 at 21:52









sdaau

2,59563148




2,59563148








  • 1




    Try melt < <(sed 's/#.*$//' test_c.melt)
    – Costas
    Jan 28 '15 at 21:55










  • Thanks @Costas - tried that, but apparently melt doesn't care about commands piped through stdin, since I get: Usage: melt [options] [producer [name=value]* ]+ and a dump of program options. Cheers!
    – sdaau
    Jan 28 '15 at 22:00






  • 1




    I have to read man melt on behalf of you. "If no files are specified, the compression is applied to the standard input". So sed 's/#.*$//' test_c.melt | melt > result.file can work.
    – Costas
    Jan 28 '15 at 22:07










  • Thanks again, @Costas - unfortunately, that doesn't work either, at least not on my version of melt (MLT melt 0.6.2; "standard input" is not mentioned in this version's man melt), since for that command, again I get Usage: melt [options] [producer [name=value]* ]+ and a dump. Cheers!
    – sdaau
    Jan 28 '15 at 22:10












  • I think you have to read man melt on your machine. If you cannot find answer post in on pastebin.com and post link here.
    – Costas
    Jan 28 '15 at 22:15














  • 1




    Try melt < <(sed 's/#.*$//' test_c.melt)
    – Costas
    Jan 28 '15 at 21:55










  • Thanks @Costas - tried that, but apparently melt doesn't care about commands piped through stdin, since I get: Usage: melt [options] [producer [name=value]* ]+ and a dump of program options. Cheers!
    – sdaau
    Jan 28 '15 at 22:00






  • 1




    I have to read man melt on behalf of you. "If no files are specified, the compression is applied to the standard input". So sed 's/#.*$//' test_c.melt | melt > result.file can work.
    – Costas
    Jan 28 '15 at 22:07










  • Thanks again, @Costas - unfortunately, that doesn't work either, at least not on my version of melt (MLT melt 0.6.2; "standard input" is not mentioned in this version's man melt), since for that command, again I get Usage: melt [options] [producer [name=value]* ]+ and a dump. Cheers!
    – sdaau
    Jan 28 '15 at 22:10












  • I think you have to read man melt on your machine. If you cannot find answer post in on pastebin.com and post link here.
    – Costas
    Jan 28 '15 at 22:15








1




1




Try melt < <(sed 's/#.*$//' test_c.melt)
– Costas
Jan 28 '15 at 21:55




Try melt < <(sed 's/#.*$//' test_c.melt)
– Costas
Jan 28 '15 at 21:55












Thanks @Costas - tried that, but apparently melt doesn't care about commands piped through stdin, since I get: Usage: melt [options] [producer [name=value]* ]+ and a dump of program options. Cheers!
– sdaau
Jan 28 '15 at 22:00




Thanks @Costas - tried that, but apparently melt doesn't care about commands piped through stdin, since I get: Usage: melt [options] [producer [name=value]* ]+ and a dump of program options. Cheers!
– sdaau
Jan 28 '15 at 22:00




1




1




I have to read man melt on behalf of you. "If no files are specified, the compression is applied to the standard input". So sed 's/#.*$//' test_c.melt | melt > result.file can work.
– Costas
Jan 28 '15 at 22:07




I have to read man melt on behalf of you. "If no files are specified, the compression is applied to the standard input". So sed 's/#.*$//' test_c.melt | melt > result.file can work.
– Costas
Jan 28 '15 at 22:07












Thanks again, @Costas - unfortunately, that doesn't work either, at least not on my version of melt (MLT melt 0.6.2; "standard input" is not mentioned in this version's man melt), since for that command, again I get Usage: melt [options] [producer [name=value]* ]+ and a dump. Cheers!
– sdaau
Jan 28 '15 at 22:10






Thanks again, @Costas - unfortunately, that doesn't work either, at least not on my version of melt (MLT melt 0.6.2; "standard input" is not mentioned in this version's man melt), since for that command, again I get Usage: melt [options] [producer [name=value]* ]+ and a dump. Cheers!
– sdaau
Jan 28 '15 at 22:10














I think you have to read man melt on your machine. If you cannot find answer post in on pastebin.com and post link here.
– Costas
Jan 28 '15 at 22:15




I think you have to read man melt on your machine. If you cannot find answer post in on pastebin.com and post link here.
– Costas
Jan 28 '15 at 22:15










4 Answers
4






active

oldest

votes

















up vote
3
down vote



accepted










A possibility would be to point melt to a filesystem that shows modified copies of files. FUSE is a generic way to build filesystem driver implemented by an ordinary program and requiring no privileges. There are many FUSE filesystems around, and there's a good chance that one of them can help you. The idea is to provide a mount point where reading a .melt file reads the “real” file but with comments filtered out.



ScriptFS looks promising (but I've never used it). Something like this should work:



mkdir ~/uncommented-melt
scriptfs -p "$HOME/bin/uncomment-melt;&*.melt" ~/work ~/uncommented-melt


where ~/work is the root of the tree that contains your .melt files and ~/bin/uncomment-melt is



#!/bin/sh
sed 's/#.*$//' "$1"


Then if you have a file ~/work/test_c.melt with comments, you can run melt ~/uncommented-melt/test_c.melt.



Other potential helpful FUSE filesystems:





  • Execfuse — lets you build a simple FUSE driver with shell scripts


  • AVFS or other FUSE filesystems that transparently uncompress files: define the stripping of comments as an uncompression rule.






share|improve this answer





















  • Many thanks for that @Gilles - I accepted this answer, because it answer the question generically. Unfortunately, I couldn't quite get scriptfs to work - here is a command log I saved at the time (AFAICR, stackexchange crashed that day :)) gist.github.com/anonymous/e9ee5e8c53d1b4c3c736 - so I ended up using a bash script approach which I posted below. Cheers!
    – sdaau
    Feb 23 '15 at 16:35


















up vote
1
down vote













Ok, it turns out that in my specific case, these kind of melt scripts are to be interpreted strictly as commands line arguments; so just the one sed in the OP doesn't quite cut it (plus, there are other things like profiles that can be set). So here is what I ended up doing - can probably serve as inspiration in other cases which the title of the OP would cover.



I eventually settled on using this: make a test.shmelt file, which is actually a bash script that contains my commented melt script code; make this file executable chmod +x test.shmelt; then after editing the script, run it as ./test.shmelt.



Upon running, it will create a "cleaned up" test.melt file in /tmp, and call melt on this file instead. Since melt usually keeps running in terminal after the end of its programme, with a trap on SIGINT this temporary file can be cleaned up when Ctrl-C is pressed (but doesn't have to).



In that way, I still have comments; can edit quickly in the source file and run melt and see results; and have a file "cleaned up" of comments too, that I can use later.



Here is the code of 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





share|improve this answer




























    up vote
    1
    down vote













    It's been a while, but I'll try to answer the title question in a way that would've been useful to me.



    This is related: Why does BASH process substitution not work with some commands?



    So the specific problem I was trying to solve was this:




    1. I have an image converter;

    2. it converts from [insert random format] to simple formats like BMP/PNM/TGA;

    3. I want to convert to JPEG, so need to chain it with ImageMagick convert;

    4. I don't want to use temporary files.


    So, unfortunately, the tool doesn't like to output to stdout/fds/pipes because it derives the output format from the output filename's extension. So how to trick it?



    Create a soft link with the appropriate extension to /dev/fd/N and use that as the "temporary file".



    Example:



    ln -s /dev/fd/4 temp.pnm
    [TOOL] -i [INPUTFILE] -o temp.pnm 4>&1 | convert - [OUTPUT.JPG]





    share|improve this answer




























      up vote
      0
      down vote













      With the zsh shell, you can use the =(...) form of process substitution (which uses temporary files instead of /dev/fd/x files and pipes) for which you can specify a suffix:



      (TMPSUFFIX=.melt; melt =(sed 's/#.*$//' test_c.melt))


      See info zsh TMPSUFFIX (assuming the info pages are installed, you may need to install a zsh-doc package) for details.






      share|improve this answer





















        Your Answer








        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "106"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        convertImagesToLinks: false,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: null,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });














        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f181673%2fusing-process-substitution-to-trick-programs-expecting-files-with-specific-exte%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        4 Answers
        4






        active

        oldest

        votes








        4 Answers
        4






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes








        up vote
        3
        down vote



        accepted










        A possibility would be to point melt to a filesystem that shows modified copies of files. FUSE is a generic way to build filesystem driver implemented by an ordinary program and requiring no privileges. There are many FUSE filesystems around, and there's a good chance that one of them can help you. The idea is to provide a mount point where reading a .melt file reads the “real” file but with comments filtered out.



        ScriptFS looks promising (but I've never used it). Something like this should work:



        mkdir ~/uncommented-melt
        scriptfs -p "$HOME/bin/uncomment-melt;&*.melt" ~/work ~/uncommented-melt


        where ~/work is the root of the tree that contains your .melt files and ~/bin/uncomment-melt is



        #!/bin/sh
        sed 's/#.*$//' "$1"


        Then if you have a file ~/work/test_c.melt with comments, you can run melt ~/uncommented-melt/test_c.melt.



        Other potential helpful FUSE filesystems:





        • Execfuse — lets you build a simple FUSE driver with shell scripts


        • AVFS or other FUSE filesystems that transparently uncompress files: define the stripping of comments as an uncompression rule.






        share|improve this answer





















        • Many thanks for that @Gilles - I accepted this answer, because it answer the question generically. Unfortunately, I couldn't quite get scriptfs to work - here is a command log I saved at the time (AFAICR, stackexchange crashed that day :)) gist.github.com/anonymous/e9ee5e8c53d1b4c3c736 - so I ended up using a bash script approach which I posted below. Cheers!
          – sdaau
          Feb 23 '15 at 16:35















        up vote
        3
        down vote



        accepted










        A possibility would be to point melt to a filesystem that shows modified copies of files. FUSE is a generic way to build filesystem driver implemented by an ordinary program and requiring no privileges. There are many FUSE filesystems around, and there's a good chance that one of them can help you. The idea is to provide a mount point where reading a .melt file reads the “real” file but with comments filtered out.



        ScriptFS looks promising (but I've never used it). Something like this should work:



        mkdir ~/uncommented-melt
        scriptfs -p "$HOME/bin/uncomment-melt;&*.melt" ~/work ~/uncommented-melt


        where ~/work is the root of the tree that contains your .melt files and ~/bin/uncomment-melt is



        #!/bin/sh
        sed 's/#.*$//' "$1"


        Then if you have a file ~/work/test_c.melt with comments, you can run melt ~/uncommented-melt/test_c.melt.



        Other potential helpful FUSE filesystems:





        • Execfuse — lets you build a simple FUSE driver with shell scripts


        • AVFS or other FUSE filesystems that transparently uncompress files: define the stripping of comments as an uncompression rule.






        share|improve this answer





















        • Many thanks for that @Gilles - I accepted this answer, because it answer the question generically. Unfortunately, I couldn't quite get scriptfs to work - here is a command log I saved at the time (AFAICR, stackexchange crashed that day :)) gist.github.com/anonymous/e9ee5e8c53d1b4c3c736 - so I ended up using a bash script approach which I posted below. Cheers!
          – sdaau
          Feb 23 '15 at 16:35













        up vote
        3
        down vote



        accepted







        up vote
        3
        down vote



        accepted






        A possibility would be to point melt to a filesystem that shows modified copies of files. FUSE is a generic way to build filesystem driver implemented by an ordinary program and requiring no privileges. There are many FUSE filesystems around, and there's a good chance that one of them can help you. The idea is to provide a mount point where reading a .melt file reads the “real” file but with comments filtered out.



        ScriptFS looks promising (but I've never used it). Something like this should work:



        mkdir ~/uncommented-melt
        scriptfs -p "$HOME/bin/uncomment-melt;&*.melt" ~/work ~/uncommented-melt


        where ~/work is the root of the tree that contains your .melt files and ~/bin/uncomment-melt is



        #!/bin/sh
        sed 's/#.*$//' "$1"


        Then if you have a file ~/work/test_c.melt with comments, you can run melt ~/uncommented-melt/test_c.melt.



        Other potential helpful FUSE filesystems:





        • Execfuse — lets you build a simple FUSE driver with shell scripts


        • AVFS or other FUSE filesystems that transparently uncompress files: define the stripping of comments as an uncompression rule.






        share|improve this answer












        A possibility would be to point melt to a filesystem that shows modified copies of files. FUSE is a generic way to build filesystem driver implemented by an ordinary program and requiring no privileges. There are many FUSE filesystems around, and there's a good chance that one of them can help you. The idea is to provide a mount point where reading a .melt file reads the “real” file but with comments filtered out.



        ScriptFS looks promising (but I've never used it). Something like this should work:



        mkdir ~/uncommented-melt
        scriptfs -p "$HOME/bin/uncomment-melt;&*.melt" ~/work ~/uncommented-melt


        where ~/work is the root of the tree that contains your .melt files and ~/bin/uncomment-melt is



        #!/bin/sh
        sed 's/#.*$//' "$1"


        Then if you have a file ~/work/test_c.melt with comments, you can run melt ~/uncommented-melt/test_c.melt.



        Other potential helpful FUSE filesystems:





        • Execfuse — lets you build a simple FUSE driver with shell scripts


        • AVFS or other FUSE filesystems that transparently uncompress files: define the stripping of comments as an uncompression rule.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jan 28 '15 at 22:14









        Gilles

        523k12610461576




        523k12610461576












        • Many thanks for that @Gilles - I accepted this answer, because it answer the question generically. Unfortunately, I couldn't quite get scriptfs to work - here is a command log I saved at the time (AFAICR, stackexchange crashed that day :)) gist.github.com/anonymous/e9ee5e8c53d1b4c3c736 - so I ended up using a bash script approach which I posted below. Cheers!
          – sdaau
          Feb 23 '15 at 16:35


















        • Many thanks for that @Gilles - I accepted this answer, because it answer the question generically. Unfortunately, I couldn't quite get scriptfs to work - here is a command log I saved at the time (AFAICR, stackexchange crashed that day :)) gist.github.com/anonymous/e9ee5e8c53d1b4c3c736 - so I ended up using a bash script approach which I posted below. Cheers!
          – sdaau
          Feb 23 '15 at 16:35
















        Many thanks for that @Gilles - I accepted this answer, because it answer the question generically. Unfortunately, I couldn't quite get scriptfs to work - here is a command log I saved at the time (AFAICR, stackexchange crashed that day :)) gist.github.com/anonymous/e9ee5e8c53d1b4c3c736 - so I ended up using a bash script approach which I posted below. Cheers!
        – sdaau
        Feb 23 '15 at 16:35




        Many thanks for that @Gilles - I accepted this answer, because it answer the question generically. Unfortunately, I couldn't quite get scriptfs to work - here is a command log I saved at the time (AFAICR, stackexchange crashed that day :)) gist.github.com/anonymous/e9ee5e8c53d1b4c3c736 - so I ended up using a bash script approach which I posted below. Cheers!
        – sdaau
        Feb 23 '15 at 16:35












        up vote
        1
        down vote













        Ok, it turns out that in my specific case, these kind of melt scripts are to be interpreted strictly as commands line arguments; so just the one sed in the OP doesn't quite cut it (plus, there are other things like profiles that can be set). So here is what I ended up doing - can probably serve as inspiration in other cases which the title of the OP would cover.



        I eventually settled on using this: make a test.shmelt file, which is actually a bash script that contains my commented melt script code; make this file executable chmod +x test.shmelt; then after editing the script, run it as ./test.shmelt.



        Upon running, it will create a "cleaned up" test.melt file in /tmp, and call melt on this file instead. Since melt usually keeps running in terminal after the end of its programme, with a trap on SIGINT this temporary file can be cleaned up when Ctrl-C is pressed (but doesn't have to).



        In that way, I still have comments; can edit quickly in the source file and run melt and see results; and have a file "cleaned up" of comments too, that I can use later.



        Here is the code of 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





        share|improve this answer

























          up vote
          1
          down vote













          Ok, it turns out that in my specific case, these kind of melt scripts are to be interpreted strictly as commands line arguments; so just the one sed in the OP doesn't quite cut it (plus, there are other things like profiles that can be set). So here is what I ended up doing - can probably serve as inspiration in other cases which the title of the OP would cover.



          I eventually settled on using this: make a test.shmelt file, which is actually a bash script that contains my commented melt script code; make this file executable chmod +x test.shmelt; then after editing the script, run it as ./test.shmelt.



          Upon running, it will create a "cleaned up" test.melt file in /tmp, and call melt on this file instead. Since melt usually keeps running in terminal after the end of its programme, with a trap on SIGINT this temporary file can be cleaned up when Ctrl-C is pressed (but doesn't have to).



          In that way, I still have comments; can edit quickly in the source file and run melt and see results; and have a file "cleaned up" of comments too, that I can use later.



          Here is the code of 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





          share|improve this answer























            up vote
            1
            down vote










            up vote
            1
            down vote









            Ok, it turns out that in my specific case, these kind of melt scripts are to be interpreted strictly as commands line arguments; so just the one sed in the OP doesn't quite cut it (plus, there are other things like profiles that can be set). So here is what I ended up doing - can probably serve as inspiration in other cases which the title of the OP would cover.



            I eventually settled on using this: make a test.shmelt file, which is actually a bash script that contains my commented melt script code; make this file executable chmod +x test.shmelt; then after editing the script, run it as ./test.shmelt.



            Upon running, it will create a "cleaned up" test.melt file in /tmp, and call melt on this file instead. Since melt usually keeps running in terminal after the end of its programme, with a trap on SIGINT this temporary file can be cleaned up when Ctrl-C is pressed (but doesn't have to).



            In that way, I still have comments; can edit quickly in the source file and run melt and see results; and have a file "cleaned up" of comments too, that I can use later.



            Here is the code of 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





            share|improve this answer












            Ok, it turns out that in my specific case, these kind of melt scripts are to be interpreted strictly as commands line arguments; so just the one sed in the OP doesn't quite cut it (plus, there are other things like profiles that can be set). So here is what I ended up doing - can probably serve as inspiration in other cases which the title of the OP would cover.



            I eventually settled on using this: make a test.shmelt file, which is actually a bash script that contains my commented melt script code; make this file executable chmod +x test.shmelt; then after editing the script, run it as ./test.shmelt.



            Upon running, it will create a "cleaned up" test.melt file in /tmp, and call melt on this file instead. Since melt usually keeps running in terminal after the end of its programme, with a trap on SIGINT this temporary file can be cleaned up when Ctrl-C is pressed (but doesn't have to).



            In that way, I still have comments; can edit quickly in the source file and run melt and see results; and have a file "cleaned up" of comments too, that I can use later.



            Here is the code of 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






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Feb 23 '15 at 16:32









            sdaau

            2,59563148




            2,59563148






















                up vote
                1
                down vote













                It's been a while, but I'll try to answer the title question in a way that would've been useful to me.



                This is related: Why does BASH process substitution not work with some commands?



                So the specific problem I was trying to solve was this:




                1. I have an image converter;

                2. it converts from [insert random format] to simple formats like BMP/PNM/TGA;

                3. I want to convert to JPEG, so need to chain it with ImageMagick convert;

                4. I don't want to use temporary files.


                So, unfortunately, the tool doesn't like to output to stdout/fds/pipes because it derives the output format from the output filename's extension. So how to trick it?



                Create a soft link with the appropriate extension to /dev/fd/N and use that as the "temporary file".



                Example:



                ln -s /dev/fd/4 temp.pnm
                [TOOL] -i [INPUTFILE] -o temp.pnm 4>&1 | convert - [OUTPUT.JPG]





                share|improve this answer

























                  up vote
                  1
                  down vote













                  It's been a while, but I'll try to answer the title question in a way that would've been useful to me.



                  This is related: Why does BASH process substitution not work with some commands?



                  So the specific problem I was trying to solve was this:




                  1. I have an image converter;

                  2. it converts from [insert random format] to simple formats like BMP/PNM/TGA;

                  3. I want to convert to JPEG, so need to chain it with ImageMagick convert;

                  4. I don't want to use temporary files.


                  So, unfortunately, the tool doesn't like to output to stdout/fds/pipes because it derives the output format from the output filename's extension. So how to trick it?



                  Create a soft link with the appropriate extension to /dev/fd/N and use that as the "temporary file".



                  Example:



                  ln -s /dev/fd/4 temp.pnm
                  [TOOL] -i [INPUTFILE] -o temp.pnm 4>&1 | convert - [OUTPUT.JPG]





                  share|improve this answer























                    up vote
                    1
                    down vote










                    up vote
                    1
                    down vote









                    It's been a while, but I'll try to answer the title question in a way that would've been useful to me.



                    This is related: Why does BASH process substitution not work with some commands?



                    So the specific problem I was trying to solve was this:




                    1. I have an image converter;

                    2. it converts from [insert random format] to simple formats like BMP/PNM/TGA;

                    3. I want to convert to JPEG, so need to chain it with ImageMagick convert;

                    4. I don't want to use temporary files.


                    So, unfortunately, the tool doesn't like to output to stdout/fds/pipes because it derives the output format from the output filename's extension. So how to trick it?



                    Create a soft link with the appropriate extension to /dev/fd/N and use that as the "temporary file".



                    Example:



                    ln -s /dev/fd/4 temp.pnm
                    [TOOL] -i [INPUTFILE] -o temp.pnm 4>&1 | convert - [OUTPUT.JPG]





                    share|improve this answer












                    It's been a while, but I'll try to answer the title question in a way that would've been useful to me.



                    This is related: Why does BASH process substitution not work with some commands?



                    So the specific problem I was trying to solve was this:




                    1. I have an image converter;

                    2. it converts from [insert random format] to simple formats like BMP/PNM/TGA;

                    3. I want to convert to JPEG, so need to chain it with ImageMagick convert;

                    4. I don't want to use temporary files.


                    So, unfortunately, the tool doesn't like to output to stdout/fds/pipes because it derives the output format from the output filename's extension. So how to trick it?



                    Create a soft link with the appropriate extension to /dev/fd/N and use that as the "temporary file".



                    Example:



                    ln -s /dev/fd/4 temp.pnm
                    [TOOL] -i [INPUTFILE] -o temp.pnm 4>&1 | convert - [OUTPUT.JPG]






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Nov 26 at 12:29









                    Nuno Cruces

                    1112




                    1112






















                        up vote
                        0
                        down vote













                        With the zsh shell, you can use the =(...) form of process substitution (which uses temporary files instead of /dev/fd/x files and pipes) for which you can specify a suffix:



                        (TMPSUFFIX=.melt; melt =(sed 's/#.*$//' test_c.melt))


                        See info zsh TMPSUFFIX (assuming the info pages are installed, you may need to install a zsh-doc package) for details.






                        share|improve this answer

























                          up vote
                          0
                          down vote













                          With the zsh shell, you can use the =(...) form of process substitution (which uses temporary files instead of /dev/fd/x files and pipes) for which you can specify a suffix:



                          (TMPSUFFIX=.melt; melt =(sed 's/#.*$//' test_c.melt))


                          See info zsh TMPSUFFIX (assuming the info pages are installed, you may need to install a zsh-doc package) for details.






                          share|improve this answer























                            up vote
                            0
                            down vote










                            up vote
                            0
                            down vote









                            With the zsh shell, you can use the =(...) form of process substitution (which uses temporary files instead of /dev/fd/x files and pipes) for which you can specify a suffix:



                            (TMPSUFFIX=.melt; melt =(sed 's/#.*$//' test_c.melt))


                            See info zsh TMPSUFFIX (assuming the info pages are installed, you may need to install a zsh-doc package) for details.






                            share|improve this answer












                            With the zsh shell, you can use the =(...) form of process substitution (which uses temporary files instead of /dev/fd/x files and pipes) for which you can specify a suffix:



                            (TMPSUFFIX=.melt; melt =(sed 's/#.*$//' test_c.melt))


                            See info zsh TMPSUFFIX (assuming the info pages are installed, you may need to install a zsh-doc package) for details.







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Nov 26 at 13:00









                            Stéphane Chazelas

                            296k54559903




                            296k54559903






























                                draft saved

                                draft discarded




















































                                Thanks for contributing an answer to Unix & Linux Stack Exchange!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.





                                Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                Please pay close attention to the following guidance:


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f181673%2fusing-process-substitution-to-trick-programs-expecting-files-with-specific-exte%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                Morgemoulin

                                Scott Moir

                                Souastre