1

If you have Pandoc installed, the following script will retrieve its HTML template, write it into a temporary file, make some adjustments, and then pass this file as a parameter:

template=$(mktemp default.html5.XXXXXX) sed -z 's/<title>.*<\/title>\s*//' <<< $(pandoc -D html) >> $template pandoc input.md -s --template $template -o output.htm rm $template 

It works, but I learn how to use Zsh effectively, and for this reason I want to change it in such a way that creating a temporary file manually won't be required.

As far as I know, Zsh process substitution feature creates temporary files automatically. For example:

${template::==(pandoc -D html)} 

But how (and whether) it is possible to re-write the original script using this technique?

1 Answer 1

3

=(cmd) expands to the path of a temporary file that contains the output of cmd and is deleted after the command =(cmd) is passed to terminates.

So it's typically to be used in pandoc --template =(cmd that generates a template)....

Now, it looks like pandoc insists on the name of the template ending in the extension for the output format, so that would be:

(TMPSUFFIX=.html pandoc input.md -s --template =( pandoc -D html | sed -z 's|<title>.*</title>\s*||' ) -o output.html ) 

$TMPPREFIX (/tmp/zsh by default) and $TMPSUFFIX (not set by default) are used to construct the names of the temporary files =(...) expand to.

If you want the path of the temp file in a variable, for instance because you want to use it for more than one file, a common approach is to pass it as argument to an anonymous function. The temp file will be removed after that function returns:

(TMPSUFFIX=.html function { for file (./*.md(N)) pandoc $file -s --template $1 -o $file:r.html } =(pandoc -D html | sed -z 's|<title>.*</title>\s*||') ) 

Or a for loop that loops just once on the expansion of =(...):

(TMPSUFFIX=.html for template (=(pandoc -D html | sed -z 's|<title>.*</title>\s*||')) for file (./*.md(N)) pandoc $file -s --template $template -o $file:r.html ) 

Here processing all the .md files in the current working directory with the same temporary template file.

It's also possible to pass =(...) to a redirection including to a compound command like in:

{ ... } < =(cmd) 

And that's when your ${var::=value} can come handy to also have the path of that file available in a variable inside the {...}:

$ { echo bar >> $file grep -H -- . $file } < ${file::==(echo foo)} /tmp/zshwBn2kk:foo /tmp/zshwBn2kk:bar 

While =(...) is very handy, it should be noted that error handling (like for other forms of command substitutions), compared to rolling out your own with mktemp is quite limited. The exit status of cmd in =(cmd) is not checked and not available including if running out of space:

zsh -c 'ls -ld -- =(yes)' yes: standard output: No space left on device -rw------- 1 chazelas chazelas 7827456 Aug 8 07:48 /tmp/zshEPwY1Q 

ls was still run even though it was not possible to get the full output of yes.

If the temp file cannot be created, zsh aborts:

$ zsh -c 'TMPPREFIX=/x; ls -ld -- =(); echo done' zsh:1: can't get a temporary filename: permission denied zsh:1: process substitution failed: permission denied 

The temp file is not removed if zsh is killed:

$ zsh -c '(){ print -r - $1; kill $$; } =()' /tmp/zshCznlPH zsh: terminated zsh -c '(){ print -r - $1; kill $$; } =()' $ ls -l /tmp/zshCznlPH -rw------- 1 chazelas chazelas 0 Aug 8 07:54 /tmp/zshCznlPH 

Manually, instead of do-something-with =(cmd) || handle-do-something-error-only $?, you'd be able to do:

file=$(mktemp) || handle-tempfile-creation-error "$?" trap 'rm -f -- "$file"' INT HUP TERM ALRM EXIT cmd > "$file" || handle-cmd-or-redirection-error "$?" do-something-with "$file" || handle-do-something-error "$?" rm -f -- "$file" trap - INT HUP TERM ALRM EXIT 

(here in sh syntax)

Where you have control at every step of the way, but that's of course a lot more cumbersome.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.