Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to modify a file when using pipes?

Tags:

bash

shell

pipe

I often have shell programming tasks where I run into this pattern:

cat file | some_script > file

This is unsafe - cat may not have read in the entire file before some_script starts writing to it. I don't really want to write the result to a temporary file (its slow, and I don't want the added complication of thinking up a unique new name).

Perhaps, there is there is a standard shell command that will buffer a whole stream until EOF is reached? Something like:

cat file | bufferUntilEOF | script > file

Ideas?

like image 248
user48956 Avatar asked Jan 18 '10 23:01

user48956


People also ask

Can you pipe to a file?

A pipe is a command that is utilized by most Linux users for redirecting the output of a command to any file. The pipe character '|' can be used to accomplish a direct connection between the output of one command as an input of the other one.

Can you use pipe in shell script?

Pipe may be the most useful tool in your shell scripting toolbox. It is one of the most used, but also, one of the most misunderstood. As a result, it is often overused or misused. This should help you use a pipe correctly and hopefully make your shell scripts much faster and more efficient.

What does it mean to pipe something in Linux?

Pipe is used to combine two or more commands, and in this, the output of one command acts as input to another command, and this command's output may act as input to the next command and so on. It can also be visualized as a temporary connection between two or more commands/ programs/ processes.

What is pipe in shell script?

The vertical bar, | , between the two commands is called a pipe. It tells the shell that we want to use the output of the command on the left as the input to the command on the right.


2 Answers

Like many others, I like to use temporary files. I use the shell process-id as part of the temporary name so that if multiple copies of the script are running at the same time, they won't conflict. Finally, I then only overwrite the original file if the script succeeds (using boolean operator short-circuiting - it's a little dense but very nice for simple command lines). Putting that all together, it would look like:

some_script < file > smscrpt.$$ && mv smscrpt.$$ file

This will leave the temporary file if the command fails. If you want to clean up on error, you can change that to:

some_script < file > smscrpt.$$ && mv smscrpt.$$ file || rm smscrpt.$$

BTW, I got rid of the poor use of cat and replaced it with input redirection.

like image 67
R Samuel Klatchko Avatar answered Oct 11 '22 02:10

R Samuel Klatchko


Another option is just to read the file into a variable:

file_contents=$(cat file)
echo "$file_contents" | script1 | script2 > file
like image 27
Bromate Avatar answered Oct 11 '22 01:10

Bromate