Bash File Descriptor Trick

Here’s a little bash trick you might not be aware of.

If you wrap a command in <( and ), you get back something that looks like a file name;

$ echo <(ls)


now, that’s not a file, but a file descriptor – a temporary path that unix programs can be tricked into treating like a file.

For example, you can cat the file descriptor just as you would a file:

$ cat <(ls)


So cat thinks it’s reading a file – cat /dev/fd/63 – but it’s actually streaming the output of a command.

So with this trick, any program that takes a file parameter can take a command output. Eg;

  • curl some web content
  • use find or ls to describe files
  • use sed, awk, and grep to modify an existing file

This can be useful when you have a program that takes multiple input files, like diff;

$ diff <(ls src) <(ls src.bak)

< canto34-syntax.test.ts
< canto34.test.ts
< example.test.ts

So here I’ve listed the contents of two directories of source files, and I can see that src has three more files in it than src.bak. Now that’s hard to do otherwise!

Or consider this example – I’ve got two files I know differ only by indentation:

$ diff src/example.ts src.bak/example.ts | wc -l

so, lots of differences. But can I prove they’re the same after trimming?

$ diff <(sed 's|^ *||' src/example.ts)  <(sed 's|^ *||' src.bak/example.ts)

<no output>

Ok then! I’ve used sed to trim leading whitespace from both files, and now the diff is empty – the files are basically the same.

Does rustc perform better on a ramdisk? (no)

So, rust is slow to compile (see for some background) and I thought it’d be interesting to see if disk i/o made a big difference on a moderate project. Would writing to a RAM disk speed things up?

Quick answer – nope. Not at all.

The approach was to run this clean build and time it;

rm -rf target/* && time cargo build

For the disk runs, nothing clever – just as normal, with target as standard directory on the SSD.

For the ram disk runs, I wrote a little script to prepare a ram disk – see this gist – and created a 6Gb ram disk to serve as the target dir like so;

cd "$HOME/src/my-rust-project/workspaces"
mv target target.disk
create-ram-disk 6 "$HOME/src/my-rust-project/workspaces/target"

The summary – it’s no different. At all.

# Results
DISK1: real   2m28.139s | user   22m20.473s | sys   1m49.867s
DISK2: real   2m35.500s | user   23m7.738s  | sys   1m55.345s
RAM1:  real   2m37.218s | user   22m43.319s | sys   1m53.874s
RAM2:  real   2m27.837s | user   22m58.143s | sys   1m56.239s

Well, maybe that saves you an afternoon of mucking about, or gives you enough info to waste some of your own time 🙂