WARNING: Without special workarounds, GNU cp --attributes-only
will truncate the destination files, at least in Precise. See the edit below.
Original:
In this situation you probably want GNU cp's --attributes-only
option, together with --archive
, as it's tried and tested code, does all filesystem-agnostic attributes and doesn't follow symlinks (following them can be bad!):
cp --archive --attributes-only /source/of/failed/backup/. /destination/
As with files, cp
is additive with extended attributes: if both source and destination have extended attributes it adds the source's extended attributes to the destination (rather than deleting all of the destination's xattrs first). While this mirrors how cp
behaves if you copy files into an existing tree, it might not be what you expect.
Also note that if you didn't preserve hard links the first time around with rsync
but want to preserve them now then cp
won't fix that for you; you're probably best off rerunning rsync
with the right options (see my other answer) and being patient.
If you found this question while looking to deliberately separate and recombine metadata/file contents then you might want to take a look at metastore which is in the Ubuntu repositories.
Source: GNU coreutils manual
Edited to add:
cp
from GNU coreutils
>= 8.17 and above will work as described, but coreutils <= 8.16 will truncate files when restoring their metadata. If in doubt, don't use cp
in this situation; use rsync
with the right options and/or be patient.
I wouldn't recommend this unless you fully understand what you're doing, but earlier GNU cp
can be prevented from truncating files using the LD_PRELOAD trick:
/*
* File: no_trunc.c
* Author: D.J. Capelis with minor changes by Zak Wilcox
*
* Compile:
* gcc -fPIC -c -o no_trunc.o no_trunc.c
* gcc -shared -o no_trunc.so no_trunc.o -ldl
*
* Use:
* LD_PRELOAD="./no_trunc.so" cp --archive --attributes-only <src...> <dest>
*/
#define _GNU_SOURCE
#include <dlfcn.h>
#define _FCNTL_H
#include <bits/fcntl.h>
extern int errorno;
int (*_open)(const char *pathname, int flags, ...);
int (*_open64)(const char *pathname, int flags, ...);
int open(const char *pathname, int flags, mode_t mode) {
_open = (int (*)(const char *pathname, int flags, ...)) dlsym(RTLD_NEXT, "open");
flags &= ~(O_TRUNC);
return _open(pathname, flags, mode);
}
int open64(const char *pathname, int flags, mode_t mode) {
_open64 = (int (*)(const char *pathname, int flags, ...)) dlsym(RTLD_NEXT, "open64");
flags &= ~(O_TRUNC);
return _open64(pathname, flags, mode);
}