J'ai un dossier qui contient un certain nombre de fichiers qui ont des liens durs (dans le même dossier ou ailleurs), et je veux dissocier ces fichiers, afin qu'ils deviennent indépendants, et les modifications de leur contenu n'affecteront aucun autre fichier (leur nombre de liens devient 1).
Ci-dessous, je donne une solution qui copie essentiellement chaque lien dur vers un autre emplacement, puis le remets en place.
Cependant, cette méthode semble plutôt grossière et sujette aux erreurs, donc j'aimerais savoir s'il existe une commande qui supprimera le lien physique d'un fichier pour moi.
Réponse grossière:
Rechercher des fichiers qui ont des liens durs ( Éditer : pour trouver également des sockets etc. qui ont des liens durs , utilisez find -not -type d -links +1
):
find -type f -links +1 # files only
find -not -type d -links +1 # files, sockets etc.
Une méthode grossière pour supprimer le lien physique d'un fichier (copiez-le vers un autre emplacement et déplacez-le en arrière):
Modifier: Comme Celada l'a dit, il est préférable de faire un cp -p ci-dessous, pour éviter de perdre les horodatages et les autorisations. Modifier: créez un répertoire temporaire et copiez-le dans un fichier en dessous, au lieu d'écraser un fichier temporaire, cela minimise le risque d'écraser certaines données, bien que la mv
commande soit toujours risquée (merci @Tobu). Modifier: essayez de créer le répertoire temporaire dans le même système de fichiers (@MikkoRantalainen).
# This is unhardlink.sh
set -e
for i in "$@"; do
temp="$(mktemp -d -- "${i%/*}/hardlnk-XXXXXXXX")"
[ -e "$temp" ] && cp -ip "$i" "$temp/tempcopy" && mv "$temp/tempcopy" "$i" && rmdir "$temp"
done
Donc, pour dissocier tous les liens physiques ( Modifier : changé -type f
en -not -type d
, voir ci-dessus):
find -not -type d -links +1 -print0 | xargs -0 unhardlink.sh
cp -i
commutateur, il m'a craché quelques messages lui demandant s'il devait remplacer./fileXXXXXX
(le$temp
fichier), même si tmpfile devrait donner des noms de fichier uniques, il doit donc y avoir être une sorte de condition de concurrence ou autre, et avec elle le risque de perdre certaines données.unhardlink.sh
devez créer un répertoire temporaire dans le même répertoire qui contient le fichier qui doit être non lié. Sinon, votre appel récursif risque de rentrer dans un autre système de fichiers et vous finirez par déplacer des éléments au-delà des limites du système de fichiers car votre répertoire temporaire se trouve dans le répertoire de travail actuel. Je suppose que vous pourriez"$(dirname "$i")/hardlink-XXXXXX"
plutôt passer l'argument à mktemp.fuse
système de fichiers, il peut en fait être distribuépath/to/hardlink-XXX
sur un autre support de stockage physiquepath/to/original-file
, mais il n'y a pas grand-chose à faire à ce sujet.Réponses:
Il y a place à amélioration dans votre script, par exemple en ajoutant une
-p
option à lacp
commande afin que les autorisations et les horodatages soient préservés tout au long de l'opération de dissociation, et vous pouvez ajouter une gestion des erreurs afin que le fichier temporaire soit supprimé en cas d'erreur, mais l'idée de base de votre solution est la seule qui fonctionnera. Pour dissocier un fichier, vous devez le copier, puis déplacer la copie sur le nom d'origine. Il n'y a pas de solution "moins grossière" et cette solution a des conditions de concurrence dans le cas où un autre processus accède au fichier en même temps.la source
Si vous souhaitez brûler de l'espace disque et que vous disposez d'une version relativement moderne de
tar
(par exemple, ce qui est sur Ubuntu 10.04 et CentOS 6), vous pouvez jouer avec l'--hard-dereference
option.Quelque chose comme:
(où j'avais couru
ln foo/[12] bar
)Depuis la page de manuel:
la source
cp -a --no-preserve=links /path/to/folder /path/to/copy && rm -rf /path/to/folder && mv /path/to/copy /path/to/folder
si je ne me trompe pas. Je suppose que votre méthode serait plus efficace, car tar impliquerait moins de recherches de disque, donc moins de thrash. On pourrait obtenir la même chose avec rsync, avec des performances encore plus faibles que la méthode cp :).tar cvf - --hard-dereference . | tar xf -
mais il pourrait y avoir une condition de concurrence critique qui ferait exploser les choses. Je ne l'ai pas essayé, et je suis peu disposé à le faire pour le moment.