How to report "sed" in-place changes
You could do it in two passes using the p
rint action on the first pass with:
find . -type f | xargs sed --quiet 's/abc/def/gp'
where --quiet
makes sed not show every line and the p
suffix shows only lines where the substitution has matched.
This has the limitation that sed will not show which files are being changed which of course could be fixed with some additional complexity.
You could use sed
's w
flag with either /dev/stderr
, /dev/tty
, /dev/fd/2
if supported on your system. E.g. with an input file
like:
foo first
second: missing
third: foo
none here
running
sed -i '/foo/{
s//bar/g
w /dev/stdout
}' file
outputs:
bar first
third: bar
though file
content was changed to:
bar first
second: missing
third: bar
none here
So in your case, running:
find . -type f -printf '\n%p:\n' -exec sed -i '/foo/{
s//bar/g
w /dev/fd/2
}' {} \;
will edit the files in-place and output:
./file1: bar stuff more bar ./file2: ./file3: bar first third: bar
You could also print something like original line >>> modified line
e.g.:
find . -type f -printf '\n%p:\n' -exec sed -i '/foo/{
h
s//bar/g
H
x
s/\n/ >>> /
w /dev/fd/2
x
}' {} \;
edits the files in-place and outputs:
./file1: foo stuff >>> bar stuff more foo >>> more bar ./file2: ./file3: foo first >>> bar first third: foo >>> third: bar
I don't think that's possible, but a workaround might be to use perl instead:
find . -type f | xargs perl -i -ne 's/abc/def/ && print STDERR'
This will print the altered lines to standard error. For example:
$ cat foo
fooabcbar
$ find . -type f | xargs perl -i -ne 's/abc/def/ && print STDERR'
foodefbar
You can also make this slightly more complex, printing the line number, file name, original line and changed line:
$ find . -type f |
xargs perl -i -ne '$was=$_; chomp($was);
s/abc/def/ && print STDERR "$ARGV($.): $was : $_"'
./foo(1): fooabcbar : foodefbar