The question here is the bold sentence below. Suppose I'm trying to do this:
diff -u <(some command) {mystery-syntax}
I am diffing the output of some command
and some data that comes from standard input—for instance, a copy-and-paste in the terminal. Like this:
$ diff -u <(echo foo) {mystery-syntax}
bar
[Ctrl-D]
--- /dev/fd/63 2021-11-04 11:28:19.360366909 -0700
+++ /dev/fd/62 2021-11-04 11:28:19.360366909 -0700
@@ -1 +1 @@
-foo
+bar
What actual syntax is the {mystery-syntax}
meta-token covering?
The diff
utility doesn't use the -
convention for specifying standard input, so we cannot use that.
One answer is: /dev/fd/0
.
$ diff -u <(echo foo) /dev/fd/0
bar
[Ctrl-D]
--- /dev/fd/63 2021-11-04 11:31:02.837040697 -0700
+++ /dev/fd/0 2021-11-04 11:30:56.807964644 -0700
@@ -1 +1 @@
-foo
+bar
OK, so we have it working in one way, on systems that have Linux-style /dev/fd
. But is there a way without referencing the /dev
filesystem, which is a system-specific implementation detail? I believe Bash process substitution is supported on systems which have mechanisms other than /dev/fd
. The manual states that:
Process substitution is supported on systems that support named pipes (FIFOs) or the /dev/fd method of naming open files.
For instance, the obvious:
diff <(echo foo) <(cat)
doesn't work; for whatever reason, even though the <(cat)
process substitution needs only the output side of cat
, cat
is nevertheless being invoked in such a way that it has no standard input:
$ diff -u <(echo foo) <(cat)
cat: -: Input/output error
--- /dev/fd/63 2021-11-04 11:33:59.303347814 -0700
+++ /dev/fd/62 2021-11-04 11:33:59.303347814 -0700
@@ -1 +0,0 @@
-foo
There are some "clever" behaviors here, too. If we explicitly redirect
/dev/fd/0
intocat
's input, that is still borked somehow:$ diff -u <(echo foo) <(cat < /dev/fd/0) cat: -: Input/output error
But! If we give
cat
it a here-document as its standard input, there is no interference:$ diff -u <(echo foo) <(cat <<<"bar") --- /dev/fd/63 2021-11-04 11:40:03.612616179 -0700 +++ /dev/fd/62 2021-11-04 11:40:03.612616179 -0700 @@ -1 +1 @@ -foo +bar
diff - -
assumes that the two arguments are the same object and doesn't read from standard input twice; but that is neither here nor there with regard to this Q&A.) – Kaz Nov 12 '21 at 20:27-
convention really isn't supported. – Kaz Nov 12 '21 at 20:27diff
with-
does not work. It's a convention required by the POSIX standard. – Kusalananda Nov 12 '21 at 20:28diff - -
case and saw that it returns without reading anything. (Why I don't remember is that I wrote this question maybe two weeks ago, and just noticed today that I hadn't finished submitting it, due to getting a warning while closing numerous browser tabs.) So I thought, oh, it's just treating-
as a file name, and optimizing the case of a file being diffed with itself. – Kaz Nov 12 '21 at 20:29diff -s - -
and you will see what happens (in short, you are comparing the same data against itself, so there should not be any output). – Kusalananda Nov 12 '21 at 20:34/dev/fd
kernel-specific thing. – Kaz Nov 12 '21 at 21:39