views:

134

answers:

7

How do you search and delete a line (not replace) from multiple files in a directory tree? I have tried programs such as grepWin and Windows Grep but they replace lines, they do not delete the entire line. What is my best option?

Example: Search for "hello" and delete any line with "hello" in it.

yo
hello hey hey
hi hello
bye 
bye

should come back

yo
bye
bye
A: 
perl -i.bak -ne 'print unless m/pattern/' file1 file2 file3 ...
William Pursell
A: 
grep -R --revert-match

might work. Some GNU grep versions do support recursive search by file mask, but I'm not sure about Windows ports.

More long but easier way,

gfind . -name "*.txt" | xargs deleteLine.bat hello

where gfind is GNU find from, for instance, unxutils.sf.net, and deleteLine.bat is like:

grep %1 --revert-match %2 > tempfile.###
move tempfile.### %2
Victor Sergienko
+1  A: 

If you have cygwin, you can use sed:

cat test.txt  | sed 's/.*hello.*//'

This will delete lines with hello, but show the blank lines. If you don't like the blan lines, you can do:

cat test.txt  | sed 's/.*hello.*//' | sed '/^$/d'

Edit: On second thought, the complete thing can be simplified as:

sed '/.*hello.*/d' test.txt

where test.txt is the file.

This will also erase all other blank lines.You can pipe a file into sed with < , not using `cat`.
Victor Sergienko
A: 

I suggest installing cygwin if you do not already have it - it is full of tools for doing things like this.

You can delete lines with sed:

sed -i '/pattern/d' filename...

The -i option tells sed to edit the file in-place. -i.bak will leave a backup file with an extension of .bak.

To process all the files in the directory tree I suggest running the command in zsh. Zsh has some funky filename expansion options compared to bash, e.g.

sed -i '/pattern/d' **/*.(c|h)

will run sed on every file from the current directory downwards that has an extension of .c or .h.

Dave Kirby
+1  A: 

With Powershell positioned in the root directory:

foreach($file in (dir -r -i *.txt -force)) { $cleaned = gc $file | where { $_ -notlike "*Hello*" }; sc $file $cleaned }

Change the .txt filter and the "Hello*" match criteria to whatever you want.

João Angelo
A: 

I found a way in grepWin or Windows Grep to do it.

Regex Search:^.hello.$\r\n Regex Replace:

(blank replace)

Nish
A: 

Assuming, the files have an extension of .foo, the following should do:

for /f %f in ('dir /s /b *.foo') do findstr /v hello %f > c:\temp\x && move /y c:\temp\x %f

hth - Rene

René Nyffenegger