Manually merge two files using diff - linux

I'd like to merge two files by doing the following:
Output the diff of the two files into a temp file and
Manually select the lines I want to copy/save.
The problem here is that diff -u only gives me a file lines of context, while I want to output the entire file in a unified format.
Is there any way diff can do this?

One option that might fit the bill for you,
sdiff : side-by-side diff of files.
sdiff -o merged.file left.file right.file
Once there, it will prompt you with what lines you want to keep from which file. Hit ? and then enter for a little help. Also man sdiff with the detailed goods.
(In my distro, these come packaged in the "diffutils" package [fedora,centos])
If you need to automate the process, you might want to try the util merge, which will mark conflicts in the files. However, that might put you back at square one.

"I want to output the entire file in a unified format. Is there any way diff can do this?"
Yes.
diff -U 9999999 file1.txt file2.txt > diff.txt
This should work, provided your files are less than 10 million lines long.

You can merge/combine the two files with diff using --
diff --line-format %L file1 file2

The easy answer is to use the -D flag to merge the files and surround the differences with C style #ifdef statements.
From the documentation:
-D NAME --ifdef=NAME
Output merged file to show `#ifdef NAME' diffs.
You can use it as follows:
$ diff -D NEWSTUFF file1 file2 > merged_file
I usually then just open the merged file in an editor and resolve the merge conflicts by hand.
You also can use options to output an ed script, etc.

If you are an emacs user, you can do this directly in emacs using the "emerge" tool:
https://www.gnu.org/software/emacs/manual/html_node/emacs/Emerge.html
Issuing M-x emerge-files will open an interactive prompt with a view of files A, B, and the merged file to allow choosing text that differs between files A & B, inserting part of A into B, and more.

Related

The diff command for files with empty content

If I want to get the difference between the 2 directories, I use the command below:
diff -aruN dir1/ dir2/ > dir.patch
so the dir.patch file should comprise all differences I want, right?
But if dir2/ contains a file with empty content, and that file is not existent in dir1/, for example,
dir1/
dir2/empty_content_file.txt ------ with empty content.
Then the diff command will not generate any patch for empty_content_file.txt, but it is a needed file.
Is there any expertise or alternative way to do this?
Thank you in advance.
It's because you're using -N option, which is added to explicitly treat absent file as empty. man diff says :
-N, --new-file
treat absent file as empty
The screenshot below shows the operation of "diff -aru" command for inexistent files in the first directory, a message "Only in xxx" will show.

How to use to diff to C++ source files and ignore the line space and comments

I have to C++ source files and I want to see the difference between the two files. But I don't want to see the diff between the comments.
Please advise.
Many thanks.
One way would be to use the pre-processor to remove the comments and pass this into diff using process substitution...
diff -uwB <(g++ -E left.cpp) <(g++ -E right.cpp)
Of course this will pull in files that you #include and expand your #define macros, too. If they haven't changed, this should be quite readable.
The switches I have passed to diff are:
-w --ignore-all-space Ignore all white space.
-B --ignore-blank-lines Ignore changes whose lines are all blank.
-u -U NUM --unified[=NUM] Output NUM (default 3) lines of unified context.

compare two files and save the difference in linux

I like to compare two text files and save the difference under linux.
I know there are tools like kdiff, diff vimdiff etc. but my expectation are as follows.
Output should be in a separate file
The difference should be quoted with colours, ex: delete line in red and added line in green something like that
It should ignore space differences
It should be an opensource tool
use tkdiff4 -w file-name1 file-name2
It fulfills all your requirements. Specific color might be an issue.
try colordiff and man diff for options for ignoring whitespace etc
Like,
#!/bin/bash
wdiff -w "\e[31m" -x "\e[0m" -y "\e[32m" -z "\e[0m" "$#";
replace \e by, well, the ASCII character with value 0x1A. Put the two commands into some file, and run it using redirection.
Save the changes to a file:
diff -Nur originalfile newfile > patchfile
Use the difference file to change the origin file:
patch originfile patchfile
I think this is the easiest way to save the changes and reload the changes.
By the way, you can use this command the create an update-package.

help - change diff symbol "<", "|" or ">" to a desired one?

diff -w command is used to create a side by side comparison diff file (instead of parallel)
i then view them using vi via ssh terminal
the changes are indicated by either "<" or "|" or ">"
Since the file i am viewing is a source code, navigating to changes alone
using above symbols is difficult since they are also in C source code.
How can i change these default symbols to desired ones ?
Kindly help. Thanks.
Instead of viewing the output of diff -w in vim, you can use vim's built-in diff:
vim -d file1 file2
This opens vim in a vertical split with both files open, and diff markings in the code. This is what it looks like:
And it works in a terminal too:
You can find a short tutorial here
According to my version of diff (2.8.1 from the GNU diffutils by the FSF) -w is used to change the width of the output; The -y parameter outputs side by side comparison. In combination, the two show no further effect than the -y parameter used alone, which means you may have an alias in your terminal profile or in the global terminal profile that aliases diff to diff -y.
I say all this because all options to change the symbols ("<", "|", and ">") conflict with the -y option. If you can live without side-by-side, you have the option of two other included output styles or defining your own. The two output styles are -c (context) and -u (unified). (For more information on what they do see the diff Wikipedia page. For more information on the options see the diff man page.)
A more in depth fix would be to use the following options:
diff --old-group-format="(deleted)---" \
--new-group-format="(added)---" \
--changed-group-format="(updated)---" \
--unchanged-group-format="(nodiff)---" \
old_file.c new_file.c
Now the old file's lines that are not present in the new file are represented by (deleted)---
The new file's lines that are not present in the old file are represented by (added)---
Lines that have been changed are represented by (updated)---
Lines common to both files are represented by (nodiff)---
Since you seem to do this often enough, you have the option of making it an alias in your terminal profile or writing a small shell script to handle it. For more options, see the manual's section on options and specifically see the section on line group formats for information on what you can put between the quotes in the format definitions.
Of course, if you must have side-by-side, try Nathan Fellman's idea above. Otherwise, there's the option of using a dedicated GUI tool for it such as Kompare.

Is there a script that would allow me to edit multiple files as if they are one file in VIM?

I prefer to edit in one large file rather than many independent files, but due to limitations in languages, source control, and the preference of team mates I need to output to many files.
What I'm looking for would recurse through all the files in a source directory and generate a single file to edit in VIM, with special file seperator markers. On save it would save the the changes to the correct file(s) ideally in a smart manner, based only on changes made.
Does something like this exist?
shar
Well, you could use shar(1), but it puts an X in front of each line that you will probably find annoying. (Shar came with my Mac but on my Linux systems you need to add a package.)
Shar is just, itself, a short shell script, so you could modify it easily enough to work without the X.
You might try copying /usr/bin/shar to /tmp and applying this diff with patch(1).
--- /usr/bin/shar 2009-07-13 22:26:18.000000000 -0700
+++ /tmp/shar2 2010-12-24 19:05:34.000000000 -0800
## -65,8 +65,8 ##
echo "mkdir -p $i > /dev/null 2>&1"
else
echo "echo x - $i"
- echo "sed 's/^X//' >$i << 'END-of-$i'"
- sed 's/^/X/' $i
+ echo "cat >$i << 'END-of-$i'"
+ cat $i
echo "END-of-$i"
fi
done
It reminds me of vimballs format. However, it's meant to expand files into the user runtimepath directory.
In other words, you can list all the files you want join and apply :MkVimBall (here is an example).
Then, for the extraction, you will have to momentarily (i.e. save and restore its value after the extraction) set &runtimepath to the root directory of your project before extracting with :so %.
You'll also have to play with various options like the &filetype, etc.
It's a dirty hack, but well ... it shall do the job.
Instead of dumping several files into one, processing this one and then separating stuff apart again, you could use bufdo or windo to repeat a command on all opened buffers: open the buffers to be processed, then cast the bufdo command and it will work on every opened file: http://vimdoc.sourceforge.net/htmldoc/windows.html#list-repeat

Resources