Explain the Linux patch command parameters and usage

  • 2020-05-14 05:44:40
  • OfStack

Speaking of the patch command, we have to mention the diff command, which is the necessary tool for making patch. diff command, when making patch files, basically only need to use the parameter diff-Nau, if the comparison is folder, also add -r parameter, so 1 directly use Naur parameter.

Function description: patch file.

Grammar: patch [-bceEflnNRstTuvZ][-B < Backup the prefix string > ][-d < Working directory > ][-D < Mark symbol > ][-F < Don't be the number of columns > ][-g < Numerical control > ][-i < Patch file > ][-o < The output file > ][-p < Stripping the hierarchy > ][-r < Declined to file > ][-V < backups > ][-Y < Backup the prefix string > ][-z < Backup the trailing character string > [-] backup if - mismatch] [-- binary] [-- help] [- nobackup if - mismatch] [-- verbose] [original file < Patch file > [-] or path p < Stripping the hierarchy > ] < [patch]

Note: the patch directive allows the user to modify and update the original file by setting the way the file is patched. If only one file is modified at a time, instructions can be issued directly in the instruction column in order to execute. This is also one of the core upgrade methods of Linux system.

Parameters:

-b or --backup backup every original file.
- B < Backup the prefix string > Or - prefix = < Backup the prefix string > When setting up a file backup, append a prefix string to the file name, which can be a path name.
-c or --context interprets the patch data as a difference in relevance.
- d < Working directory > Or - directory = < Working directory > Set the working directory.
- D < Mark symbol > Or - ifdef = < Mark symbol > Mark the change with the specified symbol.
-e or --ed interpret the patch data into a description file available for the ed directive.
-E or -- remove-empty-files if the content of the output file after the patch is 1 piece of white space, the file is removed.
-f or --force this parameter has the same effect as specifying the -t parameter, but assumes that the version of the patch data is a new version.
- F < Don't be the number of columns > Or - fuzz < Don't be the number of columns > Sets the maximum number of specified columns.
- g < Numerical control > Or - get = < Numerical control > Set RSC or SCCS to control the repair operation.
- i < Patch file > Or - input = < Patch file > Read the specified patch to ask you.
-l or - ignore-whitespace ignore patch data with the input data TAB, space character.
-n or --normal interprets the patch data as a 1-like difference.
-N or --forward ignores that the patched data is older than the version of the original file, or that the version of the patched data has been used.
- o < The output file > Or - output = < The output file > Sets the name of the output file in which the patched file will be stored.
- p < Stripping the hierarchy > Or - strip = < Stripping the hierarchy > Sets the path name for the layers you want to strip.
- f < Declined to file > Or - reject - file = < Declined to file > Set the name of the file where you want to save the rejected patching information. The default file name is.rej.
-R or --reverse assume that the patch data is generated by swapping old and new file locations.
-s or --quiet or --silent does not show instruction execution unless an error occurs.
-t or --batch automatically skips the error and asks no questions.
-T or -- set-time this parameter has the same effect as specifying the -Z parameter, but is local time oriented.
-u or --unified interprets the patch data as a 1 resulting difference.
-v or --version displays version information.
- V < backups > Or - version - control = < backups > After backing up the target file with the -b parameter, a backup string is added to the end of the backup file. This string can be changed not only with the -z parameter, but also with the -V parameter when different backup methods are specified.
- Y < Backup the prefix string > Or - basename - prefix = - < Backup the prefix string > When setting up a file backup, append the prefix string at the beginning of the file's base name.
- z < Backup the trailing character string > Or - suffix = < Backup the trailing character string > This parameter and the effect of specified - B parameters are similar, the difference is that the path and filename for repair work use src linux/fs/super c, plus backup/string, file super. c will backup in the/src/linux/fs/backup catalog.
-Z or - set-utc change the patched file to UTC access time.
-- backup-if-mismatch backs up files when patching data that does not match exactly and when it is not specified to do so.
--binary reads and writes data in base 2 mode, rather than through the standard output device.
--help online help.
-- nobackup-if-mismatch do not back up files when patching data that does not match exactly and you do not specify that you want to back them up.
--verbose shows the execution of instructions in detail.

The basic steps of the experiment. I'm going to is to set up a cascade directory. / x/xx xxx /, in xxx xxx1 directory set up two different files, xxx2. xxx.patch, xx, xx.patch, x, x.patch. Then experiment in these three categories.

Start experiment: create experiment catalogue


[King@Fedora ~]$ mkdir -pv x/xx/xxx
 mkdir:  Created directory   " x " 
mkdir:  Created directory   " x/xx " 
mkdir:  Created directory   " x/xx/xxx " 

Enter the xxx directory to create xxx1,xxx2


 [King@Fedora ~]$ cd x/xx/xxx
 [King@Fedora xxx]$ cat >> xxx1 << EOF
> 111111
 > 111111
 > EOF


 [King@Fedora xxx]$ cat >> xxx2 << EOF
 > 111111
 > 222222
 > EOF

Look at these two files


[King@Fedora xxx]$ diff -y xxx1 xxx2
111111        111111
 111111       | 222222

Be aware of the directory in which you are patching

Create the patch file xxx.patch in the xxx directory and view it.


[King@Fedora xxx]$ diff -Naru xxx1 xxx2 > xxx.patch
[King@Fedora xxx]$ cat xxx.patch 
- - - xxx1 2009-12-19 22:28:26.582959182 +0800
+++ xxx2 2009-12-19 22:28:42.798928591 +0800
 @@ -1,2 +1,2 @@
 111111
- 111111
 +222222

Create the patch file xx.patch in the xx directory and view it


[King@Fedora xxx]$ cd ..
 [King@Fedora xx]$ diff -Naru xxx/xxx1 xxx/xxx2 > xx.patch
 [King@Fedora xx]$ cat xx.patch 
--- xxx/xxx1 2009-12-19 22:28:26.582959182 +0800
 +++ xxx/xxx2 2009-12-19 22:28:42.798928591 +0800
 @@ -1,2 +1,2 @@
 111111
-111111
 +222222

Create the patch file x.patch in the x directory and view it


[King@Fedora xx]$ cd ..
 [King@Fedora x]$ diff -Nu xx/xxx/xxx1 xx/xxx/xxx2 > x.patch
 [King@Fedora x]$ cat x.patch 
--- xx/xxx/xxx1 2009-12-19 22:28:26.582959182 +0800
 +++ xx/xxx/xxx2 2009-12-19 22:28:42.798928591 +0800
 @@ -1,2 +1,2 @@
 111111
-111111
 +222222

Now copy all the patch files into the xxx directory.


[King@Fedora x]$ cp x.patch xx/xxx/
 [King@Fedora x]$ cp xx/xx.patch xx/xxx/

Enter the xxx directory to start the experiment


[King@Fedora x]$ cd xx/xxx
 [King@Fedora xxx]$ ls
 x.patch xx.patch xxx1 xxx2 xxx.patch

 [King@Fedora xxx]$ patch-p0< xxx.patch # In the first 2 One of the   The patch   Modify the   The first 1 A file 
patching file xxx1
 [King@Fedora xxx]$ cat xxx1
 111111
 222222
 [King@Fedora xxx]$ patch -RE < xxx.patch # In the first 1 One of the   The patch   Modify the   The first 1 A file 
patching file xxx1
 [King@Fedora xxx]$ cat xxx1
 111111
 111111

 [King@Fedora xxx]$ patch -p1 < xx.patch
patching file xxx1
 [King@Fedora xxx]$ cat xxx1
 111111
 222222
 [King@Fedora xxx]$ patch -RE < xxx.patch
 patching file xxx1
 [King@Fedora xxx]$ cat xxx1
 111111
 111111

 [King@Fedora xxx]$ patch -p2 < x.patch
patching file xxx1
 [King@Fedora xxx]$ cat xxx1
 111111
 222222
 [King@Fedora xxx]$ patch -RE < x.patch
 patching file xxx1
 [King@Fedora xxx]$ cat xxx1
 111111
 111111

------------------------------------------------------------


[King@Fedora xx]$ patch-p0 < xx.patch #  In the first 2 One of the   The patch   Modify the   The first 1 A file 
patching file xxx1
 [King@Fedora xxx]$ cat xxx1
 111111
 222222
 [King@Fedora xxx]$ patch -RE < xxx.patch # In the first 1 One of the   The patch   Modify the   The first 1 A file 
patching file xxx1
 [King@Fedora xxx]$ cat xxx1
 111111
 111111

 [King@Fedora xxx]$ patch -p1 < x.patch
patching file xxx1
 [King@Fedora xxx]$ cat xxx1
 111111
 222222
 [King@Fedora xxx]$ patch -RE < xxx.patch
 patching file xxx1
 [King@Fedora xxx]$ cat xxx1
 111111
 111111

--------------------------------------------------------------------------


[King@Fedora x]$ patch-p0< x.patch #  In the first 2 One of the   The patch   Modify the   The first 1 A file 
patching file xxx1
 [King@Fedora xxx]$ cat xxx1
 111111
 222222
 [King@Fedora xxx]$ patch -RE < xxx.patch # In the first 1 One of the   The patch   Modify the   The first 1 A file 
patching file xxx1
 [King@Fedora xxx]$ cat xxx1
 111111
 111111

The only thing to note here is what p0 means, because the path information in the x.patch patch file looks like this:
--- xx/xxx/xxx1

p means to skip several levels of directory, because the patch command is used in the x directory, xx directory is in the x directory, so you don't have to skip any directory, you should use -- xx/xxx/xxx1 full path, so p0 is used.

Note: patch -p cannot be followed by a negative number. When not using the p parameter, the patch command ignores any directories and USES files directly.


 [King@Fedora ~]$ cd x/xx/xxx
 [King@Fedora xxx]$ cat >> xxx1 << EOF
> 111111
 > 111111
 > EOF


 [King@Fedora xxx]$ cat >> xxx2 << EOF
 > 111111
 > 222222
 > EOF
0

As a programmer, it is essential to understand the diff&patch commands. For example, if we find that a project has the bug code, but we do not have the authority to submit, then the most appropriate solution is to use the diff command to make a patch and send it to the project members. Project members can instantly know your intentions through the patch command. Some would say it's easier to just send a new file, right? Don't forget that one patch file size is smaller and faster to transfer, and it's easy to see what changes have been made.

Make sure the current directory is demo directory:


# mkdir demo
 # cd demo

Simulate 1 project directory old:


# mkdir -p old/a/b
 # vi old/a/b/foo.txt
 old_line_1
 old_line_2

Suppose we find the old code of bug in the project old, let's first copy a new directory new and modify the bug code here:


 [King@Fedora ~]$ cd x/xx/xxx
 [King@Fedora xxx]$ cat >> xxx1 << EOF
> 111111
 > 111111
 > EOF


 [King@Fedora xxx]$ cat >> xxx2 << EOF
 > 111111
 > 222222
 > EOF
3

Make sure that old and new are both in the current directory, and then you can use the diff command. Don't use absolute paths, but relative paths.


 [King@Fedora ~]$ cd x/xx/xxx
 [King@Fedora xxx]$ cat >> xxx1 << EOF
> 111111
 > 111111
 > EOF


 [King@Fedora xxx]$ cat >> xxx2 << EOF
 > 111111
 > 222222
 > EOF
4

If you don't care about character set, time difference, etc., you can also omit LC_ALL=C TZ=UTC0 environment variable:


 [King@Fedora ~]$ cd x/xx/xxx
 [King@Fedora xxx]$ cat >> xxx1 << EOF
> 111111
 > 111111
 > EOF


 [King@Fedora xxx]$ cat >> xxx2 << EOF
 > 111111
 > 222222
 > EOF
5

Content from Linuxren.NET

The -Naur parameter is fixed, and most of the time it is used with the diff command.

Roughly browse 1 patch file:


 [King@Fedora ~]$ cd x/xx/xxx
 [King@Fedora xxx]$ cat >> xxx1 << EOF
> 111111
 > 111111
 > EOF


 [King@Fedora xxx]$ cat >> xxx2 << EOF
 > 111111
 > 222222
 > EOF
6

The content after the plus or minus sign is the useful content, and the other content is the relevant information content that is convenient for you to consult. The patch has been made.

The file directory structure at this point looks like this:


#tree
 demo
 |-- old
 | `-- a
 |  `-- b
 |   `-- foo.txt
 |-- new
 | `-- a
 |  `-- b
 |   `-- foo.txt 
-- foo.patch

Now let's see how to apply the patch using patch. Note that the current directory is demo. Try the following command:


# patch -p0 < foo.patch
 patching file old/a/b/foo.txt

The only thing to note here is what p0 means, because the path information in the foo.patch patch file looks like this:


 [King@Fedora ~]$ cd x/xx/xxx
 [King@Fedora xxx]$ cat >> xxx1 << EOF
> 111111
 > 111111
 > EOF


 [King@Fedora xxx]$ cat >> xxx2 << EOF
 > 111111
 > 222222
 > EOF
9

p said skip a few level directory, because it is used in demo directory patch command, old directory in demo directory, so don't skip any directory, but should use old/a/b/foo txt full path, so use p0 at this time.

If you look at the target file 1, you will see that the content has been changed to a new one:


# cat old/a/b/foo.txt
 new_line_1
 new_line_2

At this point, if you use the patch command again, the system will ask you if you want to restore, enter y restore:


# patch -p0 < foo.patch
 patching file old/a/b/foo.txt
 Reversed (or previously applied) patch detected! Assume -R? [n] y

If you look at the target file 1, you will see that the content has been restored to the old one:


# cat old/a/b/foo.txt
 old_line_1
 old_line_2

If you want to specify strictly that the patch should be applied, you can use the following command (that is, add the N parameter) :


# patch -Np0 < foo.patch

If you want to specify exactly how to restore the patch, you can use the following command (that is, add the R parameter) :


# patch -Rp0 < foo.patch

Note: in this example, after each application of the patch, I will not say more about restoring the patch myself in case of further experimentation.

If you're not sure about patch's p parameter, let's go ahead and change the current path by 1:


# cd old

This should be p1, not p0, and the path to the reference foo.patch file should be changed by 1, because the current directory is old: Linuxren.Net


 # patch -p1 < ../foo.patch
 patching file a/b/foo.txt

Because at this point we are using the patch command under old, level with the a subdirectory, and the path declaration in the patch file foo.patch is:


--- old/a/b/foo.txt

That means the old/ part to the left of the first slash is no longer useful. That's what p1 means!

Continue to change the path to the depth, and test the parameters of p2 and p3 successively:


# cd a

 # patch -p2 < ../../foo.patch
 patching file b/foo.txt

 # cd b

 # patch -p3 < ../../../foo.patch
 patching file foo.txt

In this case, p3 is already the deepest directory, so you can omit the p parameter:


# patch < ../../../foo.patch
 patching file foo.txt

That is, when not using the p parameter, the patch command ignores any directory and USES files directly.

Following up on why it is best to use relative paths instead of absolute paths when using the diff command?

A: if you are using the absolute path when using diff, the file path information in the patch file will look like this:

--- /a/b/c/d/e/f/g/bar.txt

This way, when someone wants to apply your patch, the directory structure must be different, so you have to work hard to determine whether to use p or not. This makes it very easy for 1 to go wrong, whereas if you use relative paths, most of the time p0 or p1 will be enough to go wrong.


Related articles: