Existe-t-il un moyen simple de remplacer tous les liens symboliques par le fichier auquel ils sont liés?
Existe-t-il un moyen simple de remplacer tous les liens symboliques par le fichier auquel ils sont liés?
Réponses:
Pour certaines définitions de «facile»:
#!/bin/sh
set -e
for link; do
test -h "$link" || continue
dir=$(dirname "$link")
reltarget=$(readlink "$link")
case $reltarget in
/*) abstarget=$reltarget;;
*) abstarget=$dir/$reltarget;;
esac
rm -fv "$link"
cp -afv "$abstarget" "$link" || {
# on failure, restore the symlink
rm -rfv "$link"
ln -sfv "$reltarget" "$link"
}
done
Exécutez ce script avec des noms de liens comme arguments, par exemple via find . -type l -exec /path/tos/script {} +
"$var"
à "${var}"
est un noop dans sh / bash. J'ai supprimé le bashism ( [[
), le reste est compatible avec POSIX sh.
cp
un fichier temporaire dans le même répertoire, puis mv -f
ce fichier temporaire dans l'original. Cela devrait se prémunir contre des problèmes tels que les personnes qui maintiennent la pression Ctrl-C
ou le remplissage du système de fichiers entre les commandes rm
et cp
(empêchant ainsi même les nouveaux ln
de fonctionner). Les noms de fichiers temporaires sont faciles à repérer ls -a
pour un nettoyage ultérieur si nécessaire.
abstarget=$(readlink -f "$link")
place du bloc de cas , mais cela pourrait avoir été des raisons de portabilité.
Il pourrait être plus facile d'utiliser simplement tar pour copier les données dans un nouveau répertoire.
-H (c and r mode only) Symbolic links named on the command line will be followed; the target of the link will be archived, not the link itself.
Vous pouvez utiliser quelque chose comme ça
tar -hcf - sourcedir | tar -xf - -C newdir
tar --help:
-H, --format=FORMAT create archive of the given format
-h, --dereference follow symlinks; archive and dump the files they point to
tar -hcf - sourcedir | tar -xf - -C newdir
cp -L
est la solution la plus simple
cp
implémentations ne copient pas les répertoires.
Si je vous ai bien compris, le -L
drapeau de la cp
commande devrait faire exactement ce que vous voulez.
Copiez simplement tous les liens symboliques et il les remplacera par les fichiers vers lesquels ils pointent.
cp -L files tmp/ && rm files && cp tmp/files .
Si vous clarifiez, vous aiderez probablement plus de gens ...
«facile» dépendra très probablement de vous.
J'écrirais probablement un script qui utilise l'utilitaire de ligne de commande "find" pour trouver des fichiers liés symboliquement, puis appelle rm et cp pour supprimer et remplacer le fichier. Vous feriez probablement bien d'avoir également l'action appelée par find check qu'il reste suffisamment d'espace libre avant de déplacer le lien sym également.
Une autre solution peut être de monter le système de fichiers en question à travers quelque chose qui cache les liens sym (comme samba), puis de tout copier. Mais dans de nombreux cas, quelque chose comme ça introduirait d'autres problèmes.
Une réponse plus directe à votre question est probablement «oui».
Modifier: selon la demande d'informations plus spécifiques. Selon la page de manuel de find , cette commande répertorie tous les fichiers de liens sym dans une profondeur de 2 répertoires, à partir de /:
find / -maxdepth 2 -type l -print
Pour que find exécute quelque chose en le trouvant:
find / -maxdepth 2 -type l -exec ./ReplaceSymLink.sh {} \;
Je crois que cela appellera un script que je viens de créer et transmettra le nom de fichier que vous venez de trouver. Alternativement, vous pouvez capturer la sortie de recherche dans un fichier (utilisez "find [blah]> symlinks.data", etc.), puis passez ce fichier dans un script que vous avez écrit pour gérer la copie gracieuse de l'original.
-exec ./ReplaceSymLink.sh {} \;
Voici le modèle que j'ai utilisé: supposez que tous les fichiers locaux sont des liens vers un autre fichier dans "source". Vous pouvez affiner la sélection de fichiers avec des modèles ou "rechercher". Veuillez comprendre avant d'utiliser.
pour f dans *; do cp --remove-destination source / $ f $ f; terminé
J'espère que cela t'aides
find . -type l -exec cp --dereference --recursive '{}' '{}'.dereferenced \;
Fera une copie de chaque fichier / dossier avec un lien symbolique <filename>.dereferenced
, ce qui est plus sûr (si moins pratique) que de les remplacer directement. Le déplacement des données copiées vers les noms de fichiers des liens symboliques est laissé comme exercice au lecteur.
find ./ -type l -print0|xargs -0 -n1 -i sh -c 'cp --remove-destination $(readlink "{}") "{}" '
basé sur /superuser//a/1301199/499386 de MastroGeppetto
Beaucoup de bonnes réponses là-bas, mais depuis que vous cherchiez quelque chose de facile
for i in *; do link=$(readlink $i) && rm $i && mv $link $i; done
J'ai eu le même problème avec gwenview lors de la copie de liens alors que vous vous attendriez normalement à ce qu'il suive le lien et copie le fichier.
Ce que j'ai fait pour «nettoyer» le répertoire en suivant tous les liens et en copiant tous les fichiers pointés dans le répertoire, a été de créer un répertoire de travail, exécutez par exemple
"for file in `ls`; do cp -L $file scratchdir/$file; done; mv scratchdir/* ./"
c'est trop dangereux de mettre dans un script car il n'y a pas de vérification mais cela a résolu mon problème.
for f in *; do cp --remove-destination $(readlink "$f") "$f"; done
J'ai fait une version en ligne, car mon hôtel Web n'autorisait pas les scripts bash et cela a bien fonctionné pour moi:
before:
> find . -type l | wc -l
358
> for link in `find . -type l` ; do echo "$link : "; ls -al $link ; cp $link notalink; unlink $link; mv notalink $link ; ls -al $link; done
...
after:
> find . -type l | wc -l
0