15

I have hundreds of files which contain "</foo:bar>"

cc
bb
aa
</foo:bar>
dd
xx
vv

I want to change them all at once to

cc
bb
aa
</foo:bar>

sed works well when i give it the exact file name

sed -i "/</foo:bar>/q" 99999.txt

but when I try to change all of them at once I get no result.

 sed -i "/<\/foo:bar>/q" *.txt
0

3 Answers 3

22

Try:

sed -s -n -i '0,/<\/foo:bar>/p' *.txt

-s tells sed to treat each file as separate.

Because we don't want sed to quit until all the files are done, we change to just print from the beginning to <\/foo:bar> and not print the rest of the lines. -n tells sed not print unless we explicitly ask it to. The command 0,/<\/foo:bar>/p tells sed to print any line in the range from the beginning of the file to the first line that matches <\/foo:bar>.

The -s option is not available for BSD/OSX sed.

2
  • @fd0 Thank you. Answer updated to note lack of -s on BSD/OSX sed.
    – John1024
    Commented Sep 13, 2016 at 15:49
  • 3
    for GNU sed, -i option implies -s ... is there a sed implementation where this solution won't work without -s option?
    – Sundeep
    Commented Jun 20, 2017 at 13:21
7

To stop reading the files when </foo:bar> is found:

With GNU awk:

gawk -i /usr/share/awk/inplace.awk '{print}; $0 == "</foo:bar>" {nextfile}' ./*.txt

With perl:

perl -ni -e 'print; close ARGV if $_ eq "</foo:bar>\n"' ./*.txt

In gawk, do not use -i inplace as gawk tries to load the inplace extension (as inplace or inplace.awk) from the current working directory first, where someone could have planted malware. The path of the inplace extension supplied with gawk may vary with the system, see the output of gawk 'BEGIN{print ENVIRON["AWKPATH"]}'

-1

Using in-place editing of files might harm them. Instead, write your changes to a new file, as shown in the example, below:

find . -maxdepth 1 -iname "*.txt" -print0 | parallel -0 "sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g; s/\"/\&quot;/g; s/'\"'\"'/\&#39;/g' {} > {}_Html_Passed.txt"

The above sed command reads each file, performs multiple substitutions of html sensitive/special characters, parallely with the help of the parallel command ( See: Installing Parallel ) and writes them to a corresponding new output file.

Also note that double quotes inside the sed command need to be escaped with a \ as the parallel command itself needs them.

The find command's -maxdepth value can be adjusted to our needs.

This code will also help those who want to publish their scripts of any kind, on the web, without getting them affected by the browser's rendering of it. Also, using the pre tags of html to surround their scripts will help.

Source : My Open Source Project

4
  • 1
    (1) What does find . -maxdepth 1 -iname "*.txt" accomplish that ./*.txt doesn’t? (aside from case-insensitivity, which the OP didn’t ask for)  (2) You have answered a different question; you have not answered this question.  (3) FYI,  ' can be encoded as &apos;. Commented May 28, 2022 at 16:18
  • Please see this : stackoverflow.com/a/3017312/16923394. and. this stackoverflow.com/a/845928/16923394 for find command's capability to support new lines in file names and its recursion abilities. Commented May 28, 2022 at 17:33
  • You’ve told me nothing I don’t already know, and you haven’t answered my question. ./*.txt handles files with newlines in their names just fine, and, by saying -maxdepth 1, you are suppressing find’s recursion abilities. Commented May 28, 2022 at 18:02
  • Quoting from my post : "The find command's -maxdepth value can be adjusted to our needs." Commented May 28, 2022 at 22:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .