0

My situation is:

  1. I have a very long text string, containing special characters, which occurs on a long line in various files. Files containing the string are throughout the file system (Linux). The string may be on various line numbers in the files where it occurs, but occurs once per file. The string, however, contains a specific pattern which I can key on for identification of the entire string.

  2. I know how to find the names of files containing the string by keying on the 'prefix' of the string using GREP -lir mystringprefix /path.

  3. I know how to determine the line number of the string in the file using GREP and SED using grep -n "prefix" file.name | sed -n “s/^([0-9])[:]./\1/p”.

  4. I know how to use SED to delete in place the line in the file containing the string of interest using sed -i xd /path/file (x is the line number to be deleted).

My question is how can I put all this together to determine which files contain the pattern, pass the name to GREP to determine the line number in the file, then pass both the name and line number to SED to remove the line?

I need to do this in such a way as to start in a certain location in the filesystem then have it search/delete recursively.

Thank you.

GWild
  • 3
  • 1
  • 2

2 Answers2

2

Pretty simple:

for file in "$(grep -lir 'prefix' /path/)" ; do
    sed -ibk -e '/prefix/d' "$file"
done

Where we presume that grep -lir prefix /path/ returns a newline-delimited list of file names and that your prefix pattern is also something sed will understand.

I don't need to determine the line number here because I am telling sed to find lines that match prefix and delete them directly. The for file in "$(grep ...)" construct is somewhat unsafe, however, because an attacker could craft a filename that would cause it to do something you don't expect. It would be better to say:

grep -lir 'prefix' /path/ --null | while IFS= read -r -d '' file ; do
    sed -ibk -e '/prefix/d' "$file"
done

Although note that variables assigned in the body of the while loop will not survive it.

sorpigal
  • 25,504
  • 8
  • 57
  • 75
  • I cannot find the SED command line switch of k in the man pages. What does that switch do? (your response also suggests that I could be served by using GREP -lirZ to enforce \0). – GWild Apr 04 '12 at 12:05
  • 1
    @GWild: `-ibk` is like `-i bk`, it's specifying the suffix to use when creating backup files when modifying. I suppose using `-i.bak` would have made this more obvious – sorpigal Apr 04 '12 at 12:28
  • Unfortunately neither example works in my case. I keep getting a SED error of "Can't find label for jump" and it references my pattern string. I do appreciate the attempted assistance. For whatever reason SED is choking on simple text. Goes to why I initially wanted the line number and to be able to pass it. GREP finds the string without issue. – GWild Apr 05 '12 at 00:28
  • 1
    I was editing my comment above longer than the alloted time. Apologies. I used the second version and it appears to have worked (not on my test system at home, but in "production"). Thank you for the assistance. – GWild Apr 05 '12 at 00:38
  • Second statement worked for me, first did not actually alter the files, just listed them – coderintherye Apr 16 '12 at 23:49
0

Pattern is case-sensitive.

grep -Zlr 'mystringprefix' /path/ | xargs -0 sed -i '/mystringprefix/d'
komar
  • 861
  • 5
  • 8