7

Possible Duplicate:
Shell programming, avoiding tempfiles

Say I have the file data.txt, and the command cmd.

cmd takes one argument, a file. Or, you could use stdin.

Now, say data.txt is uppercase, but cmd only works if all data is lowercase.

Sure, you could do this

tr '[:upper:]' '[:lower:]' < data.txt > lowercase_data.txt
cmd lowercase_data.txt
rm lowercase_data.txt

But, is there a way to integrate this?

Like, a wrapper around the original file, that applies a filter, then passes a reference to the temporary file; the command is executed; last, the temporary file is deleted?

I use zsh.

6
  • What shell are you using? Feb 4, 2013 at 0:33
  • @ReedKraft-Murphy: zsh Feb 4, 2013 at 0:33
  • As a bash user I'm not itimately familiar with zsh, but it appears to support process substitution: possibly cmd =(tr '[:upper:]' '[:lower:]' < data.txt) would do it, but I'll let someone more zsh savvy followup. Feb 4, 2013 at 0:37
  • @ReedKraft-Murphy: No, that seems to work! If bash has it, I think zsh does to :) If you convert your comment to an answer, I'll accept it. Feb 4, 2013 at 0:41
  • 1
    Since the program accepts input via stdin, why not just a plain old pipe: <data.txt tr ... | cmd?
    – Kevin
    Feb 4, 2013 at 3:14

2 Answers 2

7

zsh supports process substitution, which should do what you're asking:

A command of the form =(...) is replaced with the name of a file containing its output.

So for your example, to avoid manually creating a temporary file to pass the output of tr into cmd, you could say

cmd =(tr '[:upper:]' '[:lower:]' < data.txt)

For other shells, the equivalent would be:

  • bash: cmd <(tr '[:upper:]' '[:lower:]' < data.txt)
  • ksh: cmd <(tr '[:upper:]' '[:lower:]' < data.txt)
  • rc: cmd <{tr '[:upper:]' '[:lower:]' < data.txt}

Note that bash, ksh and rc implement process substitution using named pipes, rather than temporary files as zsh uses, and require the /dev/fd/ filesystem to be mounted

1
  • 7
    zsh also supports the same <(...) form used by bash and ksh. The =(...) is made available for situations where the command will try to do something (like seek backwards) to the argument that isn't possible with a pipe.
    – chepner
    Feb 24, 2013 at 21:30
2

There's nothing wrong with the way you do it. Except for the way you create your temp files (what if the script you're running is executed twice concurrently?).

You should use mktemp instead.

3
  • So there is no tool or well-known method to do this? You should use temporary files explicitly, only with mktemp to make it secure? Feb 4, 2013 at 0:28
  • I don't get it. mktemp is the tool you're looking for. Your usage of temporary files is totally justified. I used to ask myself the same question. Take a look at the question I link to in the comments of your question.
    – rahmu
    Feb 4, 2013 at 0:29
  • The point is not how to avoid using temporary files but to integrate that dance: create file - run command - remove file -- so that the temporary files would not have to be bothered with explicitly. Feb 4, 2013 at 0:36

Not the answer you're looking for? Browse other questions tagged or ask your own question.