Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BASH: Process Substitution in a Variable

What works is

vimdiff -c 'set diffopt+=iwhite' <(curl -sS '...') <(curl -sS '...')

Now I want to make a script that allows defining between two or four URLs and then generate the above command.

What I have for now:

#!/bin/bash

args=(-c 'set diffopt+=iwhite')
while [ -n "$1" ]; do
  args+=(<(curl -sS "$1"))
  shift
done

vimdiff "${args[@]}"

When run with two URLs it results in vimdiff showing two tabs without content and with the same filename at the bottom, e.g. "/proc/20228/fd/63". In other words the process substitution doesn't seem to be applied and/or wrong as I'd at least expect to see two different file descriptors in the filenames.

I guess that the problem is either in the args+=... line or in the last line.

like image 450
sjngm Avatar asked Sep 01 '25 01:09

sjngm


2 Answers

I think it's better to use named pipes (FIFOs) instead of <(...) to create temporary files for vimdiff, in my example,FIFOs are created for each URL provided and the output of the curl command is redirected to the corresponding named pipe and the named pipe paths are then passed as arguments to vimdiff!

#!/bin/bash

args=(-c 'set diffopt+=iwhite')
fifo_files=()

cleanup() {
  rm -f "${fifo_files[@]}"
}

trap cleanup EXIT

while [ -n "$1" ]; do
  #creating a named pipe (FIFO) and add it to the array
  fifo=$(mktemp -u)
  mkfifo "$fifo"
  fifo_files+=("$fifo")

  #using curl to write the output to the named pipe
  curl -sS "$1" > "$fifo" &

  shift
done

#pass the named pipes as arguments to vimdiff
vimdiff "${args[@]}" "${fifo_files[@]}"
like image 130
Freeman Avatar answered Sep 02 '25 16:09

Freeman


This will do the trick, and it is very close to your original proposal:

#!/bin/bash

args=(-c 'set diffopt+=iwhite')
while [ -n "$1" ]; do
  exec {fdnum}< <(curl -sS "$1")
  args+=(/dev/fd/$fdnum)
  shift
done

vimdiff "${args[@]}"

So you'd first create all file descriptors via process substitution. By accessing their content via /dev/fd, you can easily collect them in an array and pass that to vimdiff.

like image 29
Alex O Avatar answered Sep 02 '25 15:09

Alex O