POSIXly, vous utiliseriez pax
en mode lecture + écriture avec l’ -l
option:
pax -rwlpe -s /A/B/ dirA .
( -pe
Conserve tous les attributs possibles des fichiers (dans ce cas seulement les répertoires) qui sont copiés, comme GNU cp
de -a
fait).
Maintenant, bien que standard , cette commande n'est pas nécessairement très portable .
Premièrement, de nombreux systèmes basés sur GNU / Linux n'incluent pas pax
par défaut (même s'il s'agit d'un utilitaire POSIX non facultatif).
Ensuite, un certain nombre de bugs et de non-conformités avec quelques implémentations causent un certain nombre de problèmes avec ce code.
- à cause d’un bogue, Solaris 10
pax
(au moins) ne fonctionne pas -rwl
en combinaison avec -s
. Pour une raison quelconque, il semble qu'il applique la substitution à la fois au chemin d'origine et au chemin copié. Donc ci-dessus, il essaierait d'en faire link("dirB/file", "dirB/file")
au lieu de link("dirA/file", "dirB/file")
.
- sous FreeBSD,
pax
ne crée pas de liens physiques pour les fichiers de type symlink (comportement autorisé par POSIX). De plus, il applique également la substitution aux cibles des liens symboliques (comportement non autorisé par POSIX). Ainsi, par exemple, s'il y a un foo -> AA
lien symbolique dans dirA
, il deviendra foo -> BA
dans dirB
.
De plus, si vous voulez faire la même chose, mais avec des chemins de fichiers arbitraires dont le contenu est stocké dans $src
et $dst
, il est important de réaliser que pax -rwl -- "$src" "$dst"
crée la structure de répertoires complète de $src
inside $dst
(qui doit exister et être un répertoire). Par exemple, si $src
est foo/bar
, alors, $dst/foo/bar
est créé.
Si au lieu de cela, vous voulez $dst
être une copie de $src
, le plus simple est probablement de le faire comme:
absolute_dst=$(umask 077 && mkdir -p -- "$dst" && cd -P -- "$dst" && pwd -P) &&
(cd -P -- "$src" && pax -rwlpe . "$absolute_dst")
(ce qui contournerait également la plupart des problèmes mentionnés ci-dessus mais échouerait si le chemin absolu de $dst
fins se termine par des caractères de nouvelle ligne).
Maintenant, cela ne va pas aider sur les systèmes GNU / Linux où il n'y a pas pax
.
Il est intéressant de noter que pax
POSIX a été créé pour fusionner les fonctionnalités des commandes tar
et cpio
.
cpio
est une commande Unix historique (à partir de 1977) par opposition à une invention POSIX, et il existe également une implémentation GNU (pas une pax
). Ainsi, même s’il ne s’agit plus d’une commande standard (c’est le cas dans SUSv2), elle reste très courante et comporte un ensemble de fonctionnalités de base sur lesquelles vous pouvez généralement compter.
L'équivalent de pax -rwl
serait cpio -pl
. Pourtant:
cpio
prend la liste du fichier d'entrée sur stdin par opposition aux arguments (délimité par une nouvelle ligne, ce qui signifie que les noms de fichier avec des caractères de nouvelle ligne ne sont pas pris en charge)
- Tous les fichiers doivent être spécifiés (généralement, vous alimentez la sortie de
find
( find
et cpio
ont été développés conjointement par les mêmes personnes)).
- les métadonnées ne sont pas préservées (certaines
cpio
implémentations ont des options pour en conserver, mais rien n’est portable).
Donc avec cpio
:
absolute_dst=$(umask 077 && mkdir -p -- "$dst" && cd -P -- "$dst" && pwd -P) &&
(cd -P -- "$src" && find . | cpio -pl "$absolute_dst")
pax
sur FreeBSD, lescp -a
liens symboliques ne sont pas en liens durs.