1

I'm using diff and patch to patch some files. In my situation, I am not permitted to distribute any of the original file.

Right now, the diffs look something like this:

1c1
< Hello, this is the original.
---
> Hey, this is the new version.

I don't want to (and for reasons can't) include the original lines. Is it possible to make a diff that doesn't include the original lines, just what replaces the original lines?

The closest I've found is using diff -e to generate an ed script, but it doesn't look like ed is installed by default on Debian. Is it possible to do this with diff and patch?

EDIT: For example, I want to take a file that looks like this:

Hello, this is a file.
It is pretty cool.
I wrote it in a text editor.

to a file like this:

Hello, this is a file.
It is kinda awesome.
I wrote it in a text editor.

A regular diff would include the original line, and look like this:

2c2
< It is pretty cool.
---
> It is kinda awesome.

I don't want the original line ("It is pretty cool.") to even be in the diff file. I'd like a diff file that basically says replace line 2 with: It is kinda awesomewhich has all the needed info to patch, but includes none of the original content. Essentially, I want a diff that says "replace whatever is on line 2 with this:".

Running patch -e to make an ed script generates all that I need, but I don't want to use that as ed isn't included in Debian by default.

2c
It is kinda awesome.
.
8
  • 2
    No ed?!?!? ed is the standard text editor!
    – Jeff Schaller
    Feb 4, 2016 at 23:18
  • I was kind of surprised too, as it's part of POSIX, so it should be in Debian.
    – IBPX
    Feb 4, 2016 at 23:19
  • Maybe I don't understand your situation, but what about just providing the new file with instructions to copy it over the existing file?
    – Jeff Schaller
    Feb 5, 2016 at 0:33
  • Let me clarify: In my situation, I am not permitted to redistribute any of the original content, so I can't include it in the patch.
    – IBPX
    Feb 5, 2016 at 0:38
  • Off the top of my head, I'm imagining a big of sed for each file (sed 2s/.*/new text/; 5s/.*/other text/ ...). If you can't rely on -i being there for sed, you're also looking at working with temp files
    – Jeff Schaller
    Feb 5, 2016 at 1:04

3 Answers 3

2

To capture what I understand from the Q's comments, I'm going to answer that "no, it is not possible to do what you want with diff and patch", since they must include context, which includes content that you can't distribute.

Given that you can't rely on ed to be present, if you can rely on sed to be there, then you could loop through your changed files and update each one with a sed expression:

$ cp input tempfile && \
$ sed \
    -e '2s/.*/It is kinda awesome./' \
    -e '4s/.*/No really, this is line 4/' \
  tempfile > input && \
$ rm tempfile

I broke the commands up to hint at the possibility of a script-writing script that would generate the above commands, replacing "input" with the filename that needs to be changed and the "-e ..." lines with the content that needs to change. Here I'm changing whatever's on line 2 and line 4 with the corresponding text.

If you're concerned about "tempfile" colliding with an existing name, see if this spartan system has mktemp. You could save some mktemp cycles by creating one temp file to (re)use for each input file.

If this ed-less system has a sed that supports the -i flag, then you can simplify that batch to:

$ sed -i.orig \
    -e '2s/.*/It is kinda awesome./' \
    -e '4s/.*/No really, this is line 4/' \
  input

mikeserv brings up a good point with sed's 'c' command; GNU sed appears to accept the replacement text on the same line as the 'c' command, but just in case yours doesn't, here's one option:

$ cat > patch.sed
2c\
this is the new line two
4c\
this is an awesomer line four
^D
$ sed -f patch.sed input > output ## or sed -i.orig -f patch.sed input
5
  • 1
    @mikeserv, I had trouble using c\ on the same line as the replacement text; see chatroom if you're still there. I like the 'c' idea; will rework the answer a bit
    – Jeff Schaller
    Feb 5, 2016 at 3:02
  • thats possible - its really not the correct way to do it, but i figured with the -i and the specified Debian environment i might get away w/ modifying your (very good) answer as little as possible while hopefully still marginally improving it and so omitted the correct newlines there. (though you should remove the -i in my opinion...). I like your edit better. Options are good.
    – mikeserv
    Feb 5, 2016 at 3:04
  • thanks, mike; I updated the answer. tmtowtdi! it's a good day when I can solve a problem and learn something!
    – Jeff Schaller
    Feb 5, 2016 at 3:06
  • Btw, @ibpx, be sure to escape / or ' characters in any replacement text, depending on the method you choose.
    – Jeff Schaller
    Feb 5, 2016 at 3:23
  • 1
    There's more than one way to do it -- sorry, must be a perl-ism
    – Jeff Schaller
    Feb 5, 2016 at 3:32
-1
diff file1  file2  | grep ^">"

comes to mind

3
  • I mean produce a file that can be applied over the original, without containing any of the original. That command just shows me what has changed, not even where it has been changed.
    – IBPX
    Feb 4, 2016 at 23:17
  • can you update your question with a few of sample file contents ? I mean, provide dummy files' content to run diff on and the output you are trying to obtain as a result of this command
    – MelBurslan
    Feb 4, 2016 at 23:20
  • I updated the question.
    – IBPX
    Feb 4, 2016 at 23:28
-2

At least with GNU diff, it seems to be possible with suitable LFMT (line format) specifiers:

diff --new-line-format="replace line %-dn with:%c'\012'%L" --unchanged-line-format= --old-line-format= file1 file2

Tested with:

$ cat file1
Hello, this is a file.
It is pretty cool.
I wrote it in a text editor.

$ cat file2
Hello, this is a file.
It is kinda awesome.
I wrote it in a text editor.

$ diff --new-line-format="replace line %-dn with:%c'\012'%L" --unchanged-line-format= --old-line-format= file1 file2 
replace line 2 with: 
It is kinda awesome.
0

You must log in to answer this question.

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