I'm learning about diff/patch and I don't understand why the patch file created by the command sequence below doesn't create the file create_me.txt
inside the Org
directory when I try to apply it.
Creating a file
$ ls -R
Org Upd
./Org:
./Upd:
create_me.txt
$ diff -ruN Org/ Upd/ > Org.patch
$ cat Org.patch
diff -ruN Org/create_me.txt Upd/create_me.txt
--- Org/create_me.txt 1970年01月01日 01:00:00.000000000 +0100
+++ Upd/create_me.txt 2019年06月30日 21:12:36.000000000 +0200
@@ -0,0 +1 @@
+content
$ patch -p0 < Org.patch
The next patch would create the file Upd/create_me.txt,
which already exists! Assume -R? [n]
The -N --new-file
flag treats absent files such as create_me.txt
as empty files with a default timestamp inside the directory where it is missing. Deleting a file using the -N
flag (see below) works perfectly but the reverse operation results in the error message seen in the command sequence above which I can't wrap my head around.
Deleting a file
$ ls -R
Org Upd
./Org:
delete_me.txt identical.txt
./Upd:
identical.txt
$ diff -ruN Org/ Upd/ > Org.patch
$ cat Org.patch
diff -ruN Org/delete_me.txt Upd/delete_me.txt
--- Org/delete_me.txt 2019年06月30日 21:32:50.000000000 +0200
+++ Upd/delete_me.txt 1970年01月01日 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-content
$ patch -p0 < Org.patch
patching file Org/delete_me.txt
$ ls -R
Org Org.patch Upd
./Org:
identical.txt
./Upd:
identical.txt
I have seen two duplicate questions to this one (https://stackoverflow.com/questions/23528758/how-to-create-patch-for-a-new-file-and-patch-it-back-to-the-original-directory,
https://askubuntu.com/questions/975879/patch-command-cant-create-the-new-file) but none of the answers satisfy me. These answers solve the problem by changing the working directory to the original directory in which the file is going to be created and applying the patch from there. This approach works but it isn't scalable to what I'm hoping to use diff/patch for and I would therefore love a more broad solution which can be used from any directory and uses the -p0
patch flag.
Current answer's way to create a file
$ ls -R
Org Upd
./Org:
identical.txt
./Upd:
create_me.txt identical.txt
$ diff -ruN Org/ Upd/ > Org.patch
$ cat Org.patch
diff -ruN Org/create_me.txt Upd/create_me.txt
--- Org/create_me.txt 1970年01月01日 01:00:00.000000000 +0100
+++ Upd/create_me.txt 2019年06月30日 21:53:09.000000000 +0200
@@ -0,0 +1 @@
+content
$ cd Org
$ patch -p1 < ../Org.patch
patching file create_me.txt
$ ls -R ..
Org Org.patch Upd
../Org:
create_me.txt identical.txt
../Upd:
create_me.txt identical.txt
An explanation to why the current answer works and my version doesn't would also be welcome.
1 Answer 1
Your first patch, and the way you’re applying it, is asking patch
to create a file named Upd/create_me.txt
, not Org/create_me.txt
: the full path is significant. When patch
sees an entry dated at the epoch (170-01-01 00:00:00 UTC), it knows that that represents a non-existent file; if it’s the "start" entry, it knows it’s supposed to create a file, and if it’s the "end" entry, it knows it’s supposed to delete a file. The name of the file to be created or deleted is taken from the other entry.
Your second patch works in the same way: it tells patch
to delete Org/delete_me.txt
.
Your third approach works because you’re telling patch
to ignore the first part of the path, i.e. Org
or Upd
. Thus it creates a file named create_me.txt
in the current directory, Org
.
To get your first example to work, you can replace Upd/create_me.txt
with Org/create_me.txt
in the patch.
-
I guess it's OK to ask an opinion in Comments, so here goes: This
diff & patch
procedure seems well-suited to upgrading a bunch of configuration files (think/etc
) after upgrading an OS (e.g. frombuster
tobullseye
) when an in-place upgrade isn't possible. IOW,diff -ruN etc-buster/ etc-bseye/ > etc-bseye.patch
. Do you know of any projects/scripts that do this?Seamus– Seamus2022年01月19日 12:06:27 +00:00Commented Jan 19, 2022 at 12:06 -
I don’t see a question about an opinion there. I’ll answer anyway, because my answer isn’t very useful — I don’t know of anything that does this.Stephen Kitt– Stephen Kitt2022年01月19日 12:23:35 +00:00Commented Jan 19, 2022 at 12:23
-
You're correct; I guess the implied question was, "Do you think that approach might be useful?"Seamus– Seamus2022年01月19日 19:33:33 +00:00Commented Jan 19, 2022 at 19:33
-
I’ve never run into a situation where it would be all that useful, but that doesn’t mean it wouldn’t be useful for you. On systems where changes to
/etc
are important, I track them usingetckeeper
, but I’ve never needed to copy a set of changes from such a system to another, wholesale. When I was a sysadmin at a meaningful scale I used Ansible to set everything up anyway, systems weren’t managed individually.Stephen Kitt– Stephen Kitt2022年01月20日 08:33:19 +00:00Commented Jan 20, 2022 at 8:33