Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

When a command takes filenames as argument, how can I avoid creating temporary files?

+1
−0

Suppose I have a command that takes filenames as arguments, like: diff foo.txt bar.txt

What if instead of actual files, I want to use the results of a command in each?

I can use temporary files:

ls /home/alice > /tmp/alice.txt
ls /home/bob > /tmp/bob.txt
diff alice.txt bob.txt

But what if I don't want to create the files?

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

2 answers

You are accessing this answer with a direct link, so it's being shown above all other answers regardless of its score. You can return to the normal view.

+5
−0

This other answer uses process substitutions. Not every shell supports this feature. If your OS provides pathnames for file descriptors (/dev/fd/N or /proc/self/fd/N) then you can use them to achieve the desired result without process substitution and without temporary files:

ls /home/alice | { ls /home/bob | diff /dev/fd/4 -; } 4<&0 </dev/null

The result of ls /home/alice would be piped to the next command (group of commands { } in our case) via stdin of the next command, but we make it available as file descriptor 4 (4<&0). We also redirect stdin to /dev/null in case something tries to read from it while it shouldn't. In our case this "something" is the second ls. While ls does not try to read from its stdin, in general a command may.

Now the result of ls /home/alice is available to diff via its file descriptor 4. By passing /dev/fd/4 as an operand we tell diff to use the file (pipe in this case) associated with the descriptor. Note in some systems opening /dev/fd/4 results in duplicating the descriptor (i.e. referring to the same open file description), but in other systems (particularly in Linux) opening /dev/fd/4 results in opening the file anew (i.e. creating a fresh new open file description). In our case this nuance does not matter, our command should work either way.

The result of ls /home/bob is piped to diff via its stdin. By - we tell diff to read from its stdin. Note - means "stdin" only because diff interprets - this way. Not all commands interpret - as "stdin", so in general you may want to use /dev/fd/0.

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.

0 comment threads

+5
−0

What you're looking for is called process substitution.

In Bash and many bash-like shells, you can use <(foo_command --with --arguments) instead of the file path:

diff <(ls /home/alice) <(ls /home/bob)
History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.

1 comment thread

NB: I'm not marking "works for me" to encourage other folks to post better answers (if they want). Fo... (2 comments)

Sign up to answer this question »