bogomips
bogomips

Reputation: 21

Copy Update from Source to Destination Directory Issue

Normally use cp -au to update a work directory from a test directory. This normally meets expectations, until coming upon this:

guest@porteus:~$ echo Update Test
Update Test
guest@porteus:~$ mkdir /tmp/src
guest@porteus:~$ touch /tmp/src/{b,c,d}
guest@porteus:~$ ls -i /tmp/src/{b,c,d}
26019 /tmp/src/b  26020 /tmp/src/c  26025 /tmp/src/d

guest@porteus:~$ ln /tmp/src/b /tmp/src/a
guest@porteus:~$ ls -i /tmp/src
26019 a  26019 b  26020 c  26025 d

guest@porteus:~$ mkdir dst
guest@porteus:~$ cp -a /tmp/src/* dst

guest@porteus:~$ ls -i dst
26002 a  26002 b  26026 c  26034 d

guest@porteus:~$ ln -f dst/c dst/a
guest@porteus:~$ ls -il dst
total 0
26026 -rw-r--r-- 2 guest guest 0 Dec  7 00:00 a
26002 -rw-r--r-- 1 guest guest 0 Dec  7 00:00 b
26026 -rw-r--r-- 2 guest guest 0 Dec  7 00:00 c
26034 -rw-r--r-- 1 guest guest 0 Dec  7 00:00 d

guest@porteus:~$ ls -il /tmp/src/
total 0
26019 -rw-r--r-- 2 guest guest 0 Dec  7 00:00 a
26019 -rw-r--r-- 2 guest guest 0 Dec  7 00:00 b
26020 -rw-r--r-- 1 guest guest 0 Dec  7 00:00 c
26025 -rw-r--r-- 1 guest guest 0 Dec  7 00:00 d

guest@porteus:~$ cp -au /tmp/src/* dst
guest@porteus:~$ ls -il dst
total 0
26026 -rw-r--r-- 3 guest guest 0 Dec  7 00:00 a
26026 -rw-r--r-- 3 guest guest 0 Dec  7 00:00 b
26026 -rw-r--r-- 3 guest guest 0 Dec  7 00:00 c
26034 -rw-r--r-- 1 guest guest 0 Dec  7 00:00 d

Extract from this manual entry for cp:

-u, --update copy only when the SOURCE file is newer than the destination file or when the destination file is missing

The files a, b, c, d in destination directory dst, should not have been touched, as their time stamps could not have been older than their source equivalents in src. However dst/b has been touched, and in this basic example cp is not living up to the update spec.

So far the only way I can think of doing the copy update and preserving the target directory hard link structure is the following:

  1. Zip through target directory recursively
  2. If file with links found, check inode against an initially empty array of processed inodes.
  3. If no inode match found in processed inode array, search for all other files with same inode.
  4. Among files with same inode, ascertain oldest file to have been original link.
  5. Compare against file of same path in source directory. If found, copy source file to destination using cp -up
  6. Link all other files with same original inode to updated file, if inode now different.
  7. Regardless of whether file with links was updated, or not enter its inode into array of processed inodes.
  8. Repeat Steps 2 to 7, until no more files with unprocessed links found.
  9. Zip through source directory recursively using cp -up if the destination file does not exist, or has no links, files with links in destination directory being ignored.

Upvotes: 0

Views: 363

Answers (1)

Armali
Armali

Reputation: 19375

The files a, b, c, d in destination directory dst, should not have been touched, as their time stamps could not have been older than their source equivalents in src. However dst/b has been touched, and in this basic example cp is not living up to the update spec.

The observed behavior does not conflict with the update spec, since the manual says for -u: copy only when …, and the file b has not been copied, but it has been linked, which cp had to do due to the option -d, implied by -a. (Bear in mind that preserve here means to keep the attributes of the source, not those of the destination.)

So far the only way I can think of doing the copy update and preserving the target directory hard link structure is the following: …

If you want to keep the target's hard link structure, just do not use option -d, but e. g. cp -pRu ….

Upvotes: 0

Related Questions