I am working on converting one bash script to fish. I did most of it already, however there is a complex piece which has several nested and chained blocks.
Consider the following simplified piece in bash. Don't read too much into logic or commands, just follow the structure and pay attention to two subshells in ()
redirected to comm
.
dummy () {
{
comm -13 \
<(cat $CACHEDLIST | gawk '{print $1}' FS='\t' OFS='\t') \
<(cat $PDFLIST | gawk '{print $1}' FS='\t' OFS='\t') \
} | fzf
}
I converted all {}
blocks to begin; end
. Then there are two subshell blocks redirected to comm -13
which I also converted to begin; end
fish blocks and the overall block is piped to fzf
. So the end result is quite straightforward:
function dummy
begin
comm -13 \
<begin; echo "Arg1"; end \
<begin; echo "Arg2"; end \
end | fzf
end
If I run this tiny piece in shell I get:
(line 7): 'end' outside of a block
How come? My only guess is that line continuation is not respected, because the issue is definitely with two <begin; ...; end \
lines.
One way to translate this is to use an explicit named pipe in place of bash
's process substitution construct. Note that the braces around comm
aren't necessary, as there is only one command in the command group. That translates to one less begin-end pair in the fish
function.
function dummy
begin
mkfifo p1 p2
gawk '{print $1}' FS='\t' OFS='\t' "$CACHEDLIST" > p1 &
gawk '{print $1}' FS='\t' OFS='\t' "$PDFLIST" > p2 &
comm -13 p1 p2 | fzf
rm p1 p2
end
(You may want to make this more robust by creating p1
and p2
in a temp directory and making sure they get removed in the event of any error.)