0

I have a list of files and corresponding line numbers where I want to perform the substitution:

s/LOG.error/LOG.warn

There are other places where this might occur and don't want to disturb those lines. How can I do this using find and sed?

The file is formatted as:

FooBar.java 125
FooBar.java 180
FooBar2.java 128

This is what I found while searching for a way to do this:

cat filenames.txt | xargs sed -i '<get-line-number-here>s/LOG.error/LOG.warn' <get-file-name-here>
1

You'll need to split the file into partitions by destination file, and perform sed -i on each file individually. Assuming you have the file names and line numbers grouped by file name and in ascending order, you can do something like

awk '$1 != prev { if (prev) print "\047 " prev;
    prev=$1;
    printf "sed -i \047" }
  { print $2 "s/LOG\\.error/LOG.warn/" }
  END { if (prev) print "\047 " prev }' filenames.txt | sh

This is a quick and dirty hack which will break in interesting and possibly dangerous ways if the file names in the first column are not a single token.

We basically refactor your text file into a sequence of sed scripts. So your example will be turned into

sed -i '125s/LOG\.error/LOG.warn
180s/LOG\.error/LOG.warn/
' FooBar.java
sed -i '128s/LOG\.error/LOG.warn/
' FooBar2.java

which you'll notice is a sh script which contains one sed script for each file.

If you are on a *BSD platform (including Mac OS) you will need to change sed -i to sed -i '' which in Awk would be "sed -i \047\047" in order to properly embed single quotes without disturbing the surrounding shell quoting (so that entire line becomes printf "sed -i \047\047 \047" } (sic)).

| improve this answer | |
  • What can I do if i also want to find the file in the directory first and then execute this on that path of the directory. I don;t have the full path. – ayushgp Apr 11 '18 at 11:33
  • I don't understand your follow-up question. You have a file of file names and line numbers but you don't know which precise files in the directory tree it applies to? Or you have a directory tree where some directory might contain this file and you want to execute this relative to that directory? – tripleee Apr 11 '18 at 11:36
  • I have a list of files. Foobar.java for example. It resides somewhere in the pwd and is the only file with that name. In the list that I have, I just have the name and not the complete path to Foobar.java. So I want to apply find to this name first and then pass it on to awk like you suggested – ayushgp Apr 11 '18 at 11:37
  • find . -name Foobar.java -execdir something will find the file and execute something in that directory. You might have to fix this up so that something doesn't care which directory you were in when you started it (use the absolute path to the input file, or maybe refactor more decisively if you need to do it more than once or twice). – tripleee Apr 11 '18 at 11:41
  • If you do need this more than once or twice, maybe rethink how you are producing this input file in the first place. – tripleee Apr 11 '18 at 11:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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