Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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.

share|improve this question

marked as duplicate by rahmu, jasonwryan, Renan, Chris Down, Gilles Feb 4 '13 at 21:23

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

    
What shell are you using? –  Reed Kraft-Murphy Feb 4 '13 at 0:33
    
@ReedKraft-Murphy: zsh –  Emanuel Berg Feb 4 '13 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. –  Reed Kraft-Murphy Feb 4 '13 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. –  Emanuel Berg Feb 4 '13 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 '13 at 3:14

2 Answers 2

up vote 4 down vote accepted

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

share|improve this answer
1  
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 '13 at 21:30

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.

share|improve this answer
    
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? –  Emanuel Berg Feb 4 '13 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 '13 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. –  Emanuel Berg Feb 4 '13 at 0:36

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