J'ai un tas de liens symboliques vers un autre lecteur. J'ai besoin de déplacer tous les fichiers de ce lecteur qui sont référencés ailleurs afin de pouvoir le supprimer.
Marty Trenouth
Réponses:
14
Pour certaines définitions de «facile»:
#!/bin/shset-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 {} +
Merci pour l'édition, Anon, mais le script ne les noms de fichiers de poignée avec des espaces très bien, en citant des variables dans tous les endroits nécessaires. Le passage "$var"à "${var}"est un noop dans sh / bash. J'ai supprimé le bashism ( [[), le reste est compatible avec POSIX sh.
grawity
Une méthode encore plus robuste pour gérer les échecs des liens symboliques consiste à placer cpun fichier temporaire dans le même répertoire, puis mv -fce fichier temporaire dans l'original. Cela devrait se prémunir contre des problèmes tels que les personnes qui maintiennent la pression Ctrl-Cou le remplissage du système de fichiers entre les commandes rmet cp(empêchant ainsi même les nouveaux lnde fonctionner). Les noms de fichiers temporaires sont faciles à repérer ls -apour un nettoyage ultérieur si nécessaire.
M. Fooz
En remarque, je ne me souviens vraiment pas pourquoi je n'ai pas simplement utilisé à la abstarget=$(readlink -f "$link")place du bloc de cas , mais cela pourrait avoir été des raisons de portabilité.
grawity
17
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
J'adore votre solution, mais je ne comprends pas la dernière partie de votre message. Pour moi, vous devriez faire:tar -hcf - sourcedir | tar -xf - -C newdir
Seb DA ROCHA
1
D'accord, cette réponse devrait être mise à jour conformément au commentaire.
astabada
1
cp -Lest la solution la plus simple
plesiv
@plesiv true et compatible posix, mais toutes les cpimplémentations ne copient pas les répertoires.
Wyatt8740
16
Si je vous ai bien compris, le -Ldrapeau de la cpcommande devrait faire exactement ce que vous voulez.
Copiez simplement tous les liens symboliques et il les remplacera par les fichiers vers lesquels ils pointent.
Merci - presque ce dont j'avais besoin: je devais faire quelque chose comme: cp -L files tmp/ && rm files && cp tmp/files . Si vous clarifiez, vous aiderez probablement plus de gens ...
sage
5
«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 /:
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.
C'est aller chercher les articles et celui marqué comme réponse est utilisé pour remplacer les liens!
Marty Trenouth
3
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é
que diriez-vous d'utiliser readlink: pour f dans *; do cp ---- remove-destination "$ (readlink $ f)" "$ f"; fait
Diego
Oui, c'est une bonne idée, mais vous perdez un certain contrôle sur l'opération. Une limite de ma solution est qu'elle ne fonctionne pas pour les fichiers avec des blancs au milieu, ou pour des listes très longues. La solution finale est probablement de combiner le 'find --exec' ci-dessus avec le 'remove destination'. Quelqu'un veut essayer?
MastroGeppetto
les blancs au milieu devraient être atténués en mettant "$ f" entre guillemets. Voici comment je l'utilise avec "find & xargs" au lieu de "for loop": find ./ -type l -print0 | xargs -0 -n1 -i sh -c 'cp --remove-destination $ (readlink "{ } ")" {} "'Je l'ai posté comme réponse distincte pour la visibilité. superuser.com/a/1329543/499386
Diego
2
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.
Une petite amélioration aidera à trouver des liens symboliques: pour lnk dans `find. -type l`; do src = $ (readlink $ lnk) && rm $ lnk && mv $ src $ lnk; fait (non testé avec la hiérarchie cependant, soyez prudent avec les contre-coups)
Roman Susi
1
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.
Réponses:
Pour certaines définitions de «facile»:
Exécutez ce script avec des noms de liens comme arguments, par exemple via
find . -type l -exec /path/tos/script {} +
la source
"$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, puismv -f
ce fichier temporaire dans l'original. Cela devrait se prémunir contre des problèmes tels que les personnes qui maintiennent la pressionCtrl-C
ou le remplissage du système de fichiers entre les commandesrm
etcp
(empêchant ainsi même les nouveauxln
de fonctionner). Les noms de fichiers temporaires sont faciles à repérerls -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.
Vous pouvez utiliser quelque chose comme ça
la source
tar -hcf - sourcedir | tar -xf - -C newdir
cp -L
est la solution la plus simplecp
implémentations ne copient pas les répertoires.Si je vous ai bien compris, le
-L
drapeau de lacp
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.
la source
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 /:
( cela a été trouvé ici )
Pour que find exécute quelque chose en le trouvant:
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.
la source
-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.
J'espère que cela t'aides
la source
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.la source
En utilisant certaines des idées précédentes, la commande suivante remplacera récursivement chaque lien symbolique par une copie de l'original:
la source
basé sur /superuser//a/1301199/499386 de MastroGeppetto
la source
Beaucoup de bonnes réponses là-bas, mais depuis que vous cherchiez quelque chose de facile
la source
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
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.
la source
la source
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:
la source