6

This question already has an answer here:

I have this cat then sed operation:

cat ${location_x}/file_1 > ${location_y}/file2
sed -i "s/0/1/g" /${location_y}/file2

Can this be done in a single line?

I might miss such a way here, but that explanation seems to me to deal with the opposite of that, and I fail too unite the above cat and sed into one operation without double ampersand (&&) or semicolon (;) and getting closer to assume it's not possible, but it's important for me to ask here because I might be wrong.

Not all readers are English speakers are familiar with the terms "ampersand" or "semicolon" so I elaborated on these.

marked as duplicate by elbarna, muru, mdpc, Braiam, Jesse_b Feb 6 '18 at 13:26

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.

19

Yes:

sed 's/0/1/g' "$location_x/file_1" >"$location_y/file2"

Your code first makes a copy of the first file and then changes the copy using inline editing with sed -i. The code above reads from the original file, does the changes, and writes the result to the new file. There is no need for cat here.

If you're using GNU sed and if the $location_x could contain a leading -, you will need to make sure that the path is not interpreted as a command line flag:

sed -e 's/0/1/g' -- "$location_x/file_1" >"$location_y/file2"

The double dash marks the end of command line options. The alternative is to use < to redirect the contents of the file into sed. Other sed implementation (BSD sed) stops parsing the command line for options at the first non-option argument whereas GNU sed (like some other GNU software) rearranges the command line in its parsing of it.

For this particular editing operation (changing all zeros to ones), the following will also work:

tr '0' '1' <"$location_x/file_1" >"$location_y/file2"

Note that tr always reads from standard input, hence the < to redirect the input from the original file.


I notice that on your sed command line, you try to access /${location_y}/file2, which is different from the path on the line above it (the / at the start of the path). This may be a typo.

  • @Kusalananda I didn't understand this text at all If you're using GNU sed and if the $location_x could contain a leading -, you will need to make sure that the path is not interpreted as a command line flag:. What do you mean when $location_x could contain a leading -? Why would someone write - $location_x when it's not part of a command? – user9303970 Feb 6 '18 at 8:49
  • 1
    @user9303970 I added that bit aftor Stéphane commented, and it's only needed to protect the command in the case where $location_x starts with - (as in -mydir/somewhere). If you can guarantee that $x_location does not start with -, then you may disregard that whole discussion. – Kusalananda Feb 6 '18 at 8:51
  • 1
    @user9303970 It's good practice to be cautious when using user-supplied data in variables, but not needed if you have full control over the contents of those variables and know for sure that it won't cause an issue. – Kusalananda Feb 6 '18 at 8:54
  • @Kusalananda for the actual case I cope with I did: sed "s/\${domain}/${1}/g" "~/myAddons/nginx_app" > "${s_a}/${domain}.conf". I read your answer at least 3 times and I understand that my code is good, but I'm still curious to know how can it be that the sed makes the change (where?), thus making the new redirected file to be created per that change. I am amazed of "how the Bash interpreter processes the command so sophisticated that the sed makes the new redirected file to be created with its own change. intuitively I'd assume "the sed should come in the end, not in the start". – user9303970 Feb 6 '18 at 9:17
  • @user9303970 But sed comes in the end (it's the only command). It will read from the given file, do its thing, and output the result. The shell handles the plumbing (the redirection to the output file). Your initial second command is the same; it calls sed on a file, does the editing of it and outputs the result. The only difference is that by using -i, sed outputs the result to the same file that it was reading from. – Kusalananda Feb 6 '18 at 9:43
1

Alternate solution using tee just for a different approach:

cat "${location_x}/file1" |\
  tee "${location_y}/file2" |\
  sed -i "s/0/1/g"

Does the following:

-cat: Reads ${location_x}/file1 and pipes it to tee

-tee: Writes input from cat to ${location_y}/file2 and pipes it to sed

-sed: Runs your sed on the input from tee

Optional: if you want to write the output from sed to a file, just append > /path/to/file to overwrite, or >> /path/to/file to append.

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