cp

cp copies files and directories.

cp [options] source dest
cp [options] source... directory
cp [options] -t directory source...

In the first form, cp copies one source to one dest. In the other two, it copies any number of sources into a directory, keeping their names.

$ cp report.txt report-backup.txt
$ cp report.txt notes.txt /home/jack/archive/

Copying directories #

cp refuses to copy a directory unless you ask it to descend into one:

OptionEffect
-r, -R, --recursiveCopy directories, and everything inside them, recursively.
-a, --archiveCopy recursively, follow no symbolic links, and request all supported preservation attributes listed below. Equivalent to -d -R --preserve-all.

-a requests the tree structure and the supported preservation set, including owner, DACL, SACL, timestamps, hard links, executable-ness, and extended attributes. It does not guarantee a complete security-descriptor duplicate; see the component limits below. A plain -r copies the contents but gives newly created files fresh security of their own.

A recursive copy never follows a symbolic link inside the destination. If a directory being copied corresponds to an entry in the destination tree that is a symbolic link to a directory, cp refuses with "cannot overwrite non-directory with directory" rather than writing the source tree through the link. Naming a symbolic link to a directory as the destination operand itself is still allowed, as it is with GNU cp.

What a copy's security descriptor is #

This is the part of cp that is specific to Peios, so it is worth being precise.

Every file carries a security descriptor — the record of who owns it and who may do what to it. When cp creates a new destination file, that new file needs a descriptor. The defaults here describe newly created files, not a promise to replace the descriptor of an existing destination.

By default, a copy gets a fresh descriptor — it does not inherit the source's. Specifically, a plain cp:

  • gives the copy a descriptor inherited from the destination directory, exactly as if you had created a new file there;
  • makes you the owner of the copy;
  • gives the copy fresh timestamps — the copy's modification time is "now".

This is usually what you want. A file copied into your home directory should be governed by your home directory's rules and owned by you, regardless of where it came from. But when you need the copy to keep something from the source, you ask for it explicitly — with the --preserve family.

The --preserve family #

--preserve carries chosen attributes from the source onto the copy. The attributes you can preserve:

AttributeWhat it carries from the source
ownerThe owner SID.
daclThe whole DACL — every access rule on the file, inherited rules included.
saclThe whole SACL — the audit rules and the integrity label.
daclniThe DACL with inherited rules stripped out — only the rules set explicitly on the source.
saclniThe SACL with inherited rules stripped out.
timestampsThe access and modification times, not creation or change time.
linksHard-link relationships among source entries selected in this command. Links to names outside that set are not recreated.
execExecutable-ness: if the source has any POSIX execute bit, set all three execute bits on the destination; otherwise clear them. Symbolic links are skipped. This does not preserve each Unix mode bit separately.
securityExtended attributes whose names begin with security., except security.peios.sd, which is handled through the descriptor components above.
xattrsExtended attributes outside the security.* namespace. xattr is an alias.

You rarely name those individually. These options select sensible sets:

OptionPreserves
-ptimestamps and exec, both required.
--preservetimestamps only. This differs from -p.
--preserve=LISTThe comma-separated attributes you name, with no implicit attributes. Other preservation options can add or remove attributes.
--preserve-allEvery supported attribute in the table above, including exec. The full DACL/SACL selections take precedence over their inherited-rule-stripping variants.
--sdowner, dacl, sacl, including inherited ACL entries. The descriptor's group component is not selected.
--sd-explicitowner, daclni, saclni — the owner and the source's explicitly set ACL rules. The group component is not selected.
--no-preserve=LISTTurns the named attributes back off — useful to subtract from a broader option.

With no explicit preservation list, a plain copy preserves exec best-effort: failure to carry executable-ness does not fail the copy. An explicit --preserve=LIST starts with no implicit attributes, so include exec if you need it. Bare --preserve uses the list timestamps and likewise does not select exec. In contrast, -p, -a, and an explicit --preserve=exec require it. These distinctions come from the option defaults and cp's bare-option parsing; the exec handler implements the execute-bit conversion.

Preservation options combine in command-line order: requests add attributes, --no-preserve removes them, and -a or --preserve-all selects the full supported set again. For example, -a --no-preserve=exec removes executable-ness from the archive request. See the resolver.

The security selection is broader than security.peios.*: it can include compatibility attributes such as security.capability if present and readable. xattrs does not include that namespace. The attribute filters exclude security.peios.sd from both classes, so copying extended attributes cannot fill in descriptor components omitted by the SD copy. The xattr copy loop sets source attributes but does not remove destination-only attributes. Copying over an existing destination is not an exact attribute synchronization.

--sd versus --sd-explicit #

Both select the source's owner, DACL, and SACL; they differ in how they treat inherited rules.

  • --sd passes the owner and the whole source DACL and SACL, including inherited entries, to the destination's descriptor-setting operation.
  • --sd-explicit carries the owner but strips inherited entries from the source ACLs before applying them, letting the destination directory supply inheritance. Use it when copying a file into a different directory and you want the file's own tailored rules to come along while still picking up the new location's inherited rules.

Neither option selects the descriptor's GROUP component. The copy implementation selects only OWNER, DACL, and SACL; it does not request replacement of the destination's group from the source. There is no group preservation attribute. The same limit applies to -a and --preserve-all. These options are not a promise of a byte-identical descriptor or preservation of every descriptor control bit, and do not establish a complete security backup/restore procedure. When the destination already has a valid descriptor, the kernel merges selected components and their selected control bits; it retains unselected group and resource-manager state. Missing or invalid destination descriptors use a separate privileged replacement path. See the set-security contract.

For what "inherited" versus "explicit" means, see Inheritance.

When a preserve cannot be honoured #

Required preservation failures are errors in the copy operation, including required exec preservation. This differs from the best-effort executable-ness of a plain copy. Descriptor writes must pass the component's access and validation checks; a full SACL write also needs enabled SeRelabelPrivilege if its label exceeds the caller's integrity. SeSecurityPrivilege or SeRestorePrivilege alone does not guarantee that every label can be copied. See integrity-label constraints.

A recursive link-preserving copy can suppress a returned error for a source symbolic link. This includes -a: the recursive caller does not propagate that error when hard-link preservation is selected. An underlying operation may still print a diagnostic, so this is not a claim that every such failure is silent. A successful exit status does not certify that every link and its required metadata were copied.

Failure is not a rollback. Destination files or a partially copied tree may already exist when a preserve fails; the regular-file error path even attempts to truncate the destination. Treat that output as incomplete; do not delete the source or replace a known-good backup on the strength of a partial copy. Check the exit status and verify the content and each attribute you require before relying on the result.

Source-side unsupported xattr enumeration is a separate accepted case. security and xattrs name extended attributes, and some filesystems have no extended attributes at all — FAT, 9p, and a squashfs image built without an attribute table are examples. If source enumeration reports that it is unsupported, the xattr handler returns success for that step without copying attributes. This does not establish that every other copy step succeeded.

That exception applies only to source enumeration. If an attribute is read from the source but cannot be set on the destination, the attribute handler returns an error. The recursive source-symlink exception above still applies. A diagnostic can look like:

# cp -a /home/jack/notes /mnt/usb-fat/
cp: failed to set extended attributes on '/mnt/usb-fat/notes': Operation not supported

The distinction matters for -a, which requests both attribute classes: unsupported source enumeration is accepted, while a destination set failure remains a preservation error.

Overwriting an existing destination #

By default, if the destination already exists, cp overwrites it. These options change that.

OptionEffect
-i, --interactiveAsk before overwriting an existing file.
-n, --no-clobberNever overwrite an existing file; skip it silently.
-u, --update[=WHICH]Overwrite only when the source is newer than the destination. WHICH can be all, none, or older.
-f, --forceIf an existing destination cannot be opened for writing, remove it and try the copy again.
--remove-destinationRemove the destination before opening it, always — contrast --force, which only removes on failure.
-b, --backup[=CONTROL]Before overwriting, make a backup of the destination.

A backup is refused when making it would destroy the source: if the source is the file the destination's backup would be written over (for example cp --backup=simple a~ a), cp stops with an error instead of overwriting it. The check compares file identity, not spelling.

When a source is a symbolic link, cp can copy the link itself or the file it points to.

OptionEffect
-L, --dereferenceAlways follow symbolic links — copy the file they point to.
-P, --no-dereferenceNever follow symbolic links — copy the link itself.
-HFollow only the symbolic links named directly on the command line, not links found while recursing.
-dCopy symbolic links as links, and preserve hard-link structure.

Other ways to copy #

cp can also produce something other than a plain duplicate.

OptionEffect
-l, --linkCreate a hard link to the source instead of copying its data.
-s, --symbolic-linkCreate a symbolic link to the source instead of copying.
--reflink[=WHEN]Make a lightweight copy-on-write clone where the file system supports it. WHEN is always, auto, or never.
--sparse[=WHEN]Control whether runs of zero bytes are stored as holes rather than written out. WHEN is always, auto, or never.
--attributes-onlyCreate the destination and copy its attributes, but not its data.

Other options #

OptionEffect
-t, --target-directory=DIRCopy every source into DIR. Useful when the directory is not the last argument.
-T, --no-target-directoryTreat dest as a plain file even if it is a directory.
--parentsRecreate the source's leading directories under the destination.
-x, --one-file-systemDo not cross into a different file system while recursing.
--strip-trailing-slashesStrip any trailing slashes from each source argument before using it.
-v, --verbosePrint each file as it is copied.
--debugExplain in detail how each file was copied. Implies -v.
--progressShow a progress bar.

Exit status #

CodeMeaning
0No failure reached the command's exit status. Skipped entries and the recursive source-symlink error case above mean this is not proof that every file or attribute was copied.
1A copy failure was reported through the command's error path, including propagated required-preservation failures.

Source and version scope #

The preservation corrections on this page are checked against peiosutils 0.8.18, commit 3344d469. The cited implementation establishes the option selections and copy behavior at that revision. It does not establish when each behavior first shipped, prove the version installed on a particular machine, or substitute for runtime validation of a copy or restore.

Edit this page