#1 Le 13/06/2012, à 15:57
- mixout
[RESOLU]Supprimer liens durs
Bonjour
dans une arborescence donnée, comment faire pour supprimer "automatiquement" tous les (éventuels) liens durs ?
j'ai utilisé Fslint pour mettre un peu d'ordre dans plusieurs disques contenant plusieurs années de "sauvegardes" de photos et musiques.
comme j'avais une tripotée de doublons, Fslint s'en est trés bien sorti et a converti tous les doublons en liens durs.
mais maintenant, lorsque je fais
for num in $(seq 2 9); do find /mon/arborescence -links "${num}" ; done
j'obtiens comme prévu une loooongue liste de fichiers
je souhaiterais faire du ménage: un fichier = un numero d'inode (non mais !)
mais j'ai peur de rajouter
-exec rm -f {} \;
savez-vous comment je peux faire cela en étant sur de ne pas faire de bétises?
je me débrouillerai aprés avec les éventuels répertoires vides
merci par avance
Dernière modification par mixout (Le 15/06/2012, à 16:14)
#2 Le 13/06/2012, à 16:13
- credenhill
Re : [RESOLU]Supprimer liens durs
hello
déjà rajouter -type f au find car les répertoires peuvent avoir un grand nombre de hardlinks en fonction des sous répertoires
Hors ligne
#3 Le 13/06/2012, à 16:26
- mixout
Re : [RESOLU]Supprimer liens durs
bien vu
merci
#4 Le 13/06/2012, à 16:35
- nesthib
Re : [RESOLU]Supprimer liens durs
Quelques remarques.
la syntaxe $(seq 2 9) est avantageusement remplacée en bash par :
{2..9}
mais tu n'en as pas besoin ici, comprends que si tu as X fichiers, find va parcourir 8X fichiers, ce qui n'est pas très rentable. Tu peux utiliser au choix une des syntaxes suivantes :
find . -type f -and \! -links 1
find . -type f -links +1
La suite dépend de ce que tu veux vraiment faire…
si ton dossier n'est pas trop gros et que tu n'es pas sûr de toi, je te recommande d'en faire une copie avant de lancer une suppression.
Pour supprimer tous les fichiers du dossier tu peux simplement utiliser la syntaxe native de find :
find … -delete
pour être sûr de toi tu peux faire un :
find . -type f -links +1 -exec ls -l {} \; -exec rm -i {} \;
Dernière modification par nesthib (Le 13/06/2012, à 16:36)
GUL Bordeaux : Giroll – Services libres : TdCT.org
Hide in your shell, scripts & astuces : applications dans un tunnel – smart wget – trouver des pdf – install. auto de paquets – sauvegarde auto – ♥ awk
⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn
Hors ligne
#5 Le 13/06/2012, à 16:38
- credenhill
Re : [RESOLU]Supprimer liens durs
cette commande va afficher tous les fichiers qui ont le même inode, donc le compte de hardlink > 2
$ find /mon/arborescence -type f -ls | awk '{x[$1]++; xx[NR]=$0} END{for(n=1;n<=NR;){$0=xx[n++];if(x[$1]>1)print $0}}' | sort -n
Dernière modification par credenhill (Le 13/06/2012, à 16:45)
Hors ligne
#6 Le 13/06/2012, à 17:15
- nesthib
Re : [RESOLU]Supprimer liens durs
find . -type f -links +1 -exec ls -il {} \;
non ?
GUL Bordeaux : Giroll – Services libres : TdCT.org
Hide in your shell, scripts & astuces : applications dans un tunnel – smart wget – trouver des pdf – install. auto de paquets – sauvegarde auto – ♥ awk
⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn
Hors ligne
#7 Le 14/06/2012, à 08:41
- credenhill
Re : [RESOLU]Supprimer liens durs
effectivement, je ne pensais pas au -link +1, mais avec un sort à la fin
edit: on peut même économiser un exec
find . -type f -links +1 -ls ¦ sort -n
Dernière modification par credenhill (Le 14/06/2012, à 09:33)
Hors ligne
#8 Le 14/06/2012, à 08:47
- mixout
Re : [RESOLU]Supprimer liens durs
Un grand MERCI (encore !) à tous les deux
j'ai toutes les précisions qu'il me faut
#9 Le 14/06/2012, à 14:44
- mixout
Re : [RESOLU]Supprimer liens durs
dites...
si je fais
find . -type f -links +1 -ls ¦ sort -n
je vois en effet la liste de mes fichiers qui ont plus d'un lien/inode
par exemple, je vois toto ET titi qui est un lien dur de toto
donc, si je colle un
-delete
derrière ça, ne vais-je pas effacer les deux fichiers ?
Dernière modification par mixout (Le 14/06/2012, à 15:52)
#10 Le 14/06/2012, à 15:06
- credenhill
Re : [RESOLU]Supprimer liens durs
oui, il va effacer tous les fichiers trouvés par find
Hors ligne
#11 Le 14/06/2012, à 15:30
- pingouinux
Re : [RESOLU]Supprimer liens durs
Bonjour,
Je viens de faire l'essai. Apparemment, il garde un des fichiers :
$ touch a b c; ln a aa; ln a aaa; ls -li
total 0
474210 -rw-r----- 3 user user 0 2012-06-14 15:28 a
474210 -rw-r----- 3 user user 0 2012-06-14 15:28 aa
474210 -rw-r----- 3 user user 0 2012-06-14 15:28 aaa
474211 -rw-r----- 1 user user 0 2012-06-14 15:28 b
474212 -rw-r----- 1 user user 0 2012-06-14 15:28 c
$ find . -type f -links +1 -delete; ls -li
total 0
474210 -rw-r----- 1 user user 0 2012-06-14 15:28 aaa
474211 -rw-r----- 1 user user 0 2012-06-14 15:28 b
474212 -rw-r----- 1 user user 0 2012-06-14 15:28 c
Hors ligne
#12 Le 14/06/2012, à 15:37
- credenhill
Re : [RESOLU]Supprimer liens durs
effectivement, peut-être parce qu'au dernier fichier, -links +1 n'est plus vrai !!
même chose avec -exec rm {} \;
Dernière modification par credenhill (Le 14/06/2012, à 15:42)
Hors ligne
#13 Le 14/06/2012, à 15:42
- mixout
Re : [RESOLU]Supprimer liens durs
j'ai fait les memes essais que pingouinux, conclusions identiques
je suis en train de faire une sauvegarde (c'est long, il y a plus de 30000 fichiers !)
et je me lance avec le -delete (brrrr !)
Dernière modification par mixout (Le 14/06/2012, à 15:44)
#14 Le 14/06/2012, à 16:24
- nesthib
Re : [RESOLU]Supprimer liens durs
@pingouinux : exactement comme a dit credenhill, si tu fais la suppression via find elle sera faite au coup par coup, donc une fois le premier (ou plutôt l'avant dernier dans le cas d'un n-uplon) fichier trouvé le second (dernier) n'aura plus de liens et ne sera pas trouvé. Si tu voulais supprimer les deux il faudrait passer la sortie de find vers une boucle qui supprime tout le monde.
@mixout : attention, ici find supprimera le premier fichier trouvé, tu ne choisiras pas lequel, avec la solution ci-dessous tu dois confirmer manuellement la suppression :
find . -type f -links +1 -exec ls -l {} \; -exec rm -i {} \;
tout dépend du nombre de doublons dans les 30000 fichiers
GUL Bordeaux : Giroll – Services libres : TdCT.org
Hide in your shell, scripts & astuces : applications dans un tunnel – smart wget – trouver des pdf – install. auto de paquets – sauvegarde auto – ♥ awk
⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn
Hors ligne
#15 Le 15/06/2012, à 09:08
- mixout
Re : [RESOLU]Supprimer liens durs
@nesthib
Ouais, j'ai pensé à ça, le -delete va m'effacer "n'importe comment"
bon, le coté manuel de rm -i {} me rebute un peu...
j'ai pourtant remarqué un truc avec mon organisation de fichiers
puisque les doublons sont "la plupart du temps" dans des repertoires différents et imbriqués les uns dans les autres
par exemple photo_noel1.jpg se trouve dans /photos/noel/ et son lien dur dans un rep genre /photos/2010/famille/DCIM/noel2010/
ce qu'il me faudrait c'est une algorithme du genre :
rechercher les fichiers qui on des liens durs
parmi ces fichiers, ne selectionner et effacer que ceux qui sont dans un repertoire "plus bas" que leur lien
là, j'avoue que je sèche
Dernière modification par mixout (Le 15/06/2012, à 09:12)
#16 Le 15/06/2012, à 14:56
- credenhill
Re : [RESOLU]Supprimer liens durs
A la différence d'un soft link, tous les liens durs sont au même niveau et on ne peut pas dire qui pointe sur qui. Ce sont les mêmes données avec des noms de fichiers différents
essayer:
affiche l'inode, la "profondeur du fichier" et son nom:
$ find . -type f -links +1 -printf "%i\t%d\t%p\n" | sort -n
en ajoutant un bout de awk, on garde le premier fichier et on enlève les autres, ce code n'exécute rien
$ find . -type f -links +1 -printf "%i\t%d\t%p\n" | sort -n | awk '{x[$1]++} x[$1]>1 {$1=$2=""; print "rm", $0}'
Dernière modification par credenhill (Le 15/06/2012, à 15:22)
Hors ligne
#17 Le 15/06/2012, à 15:50
- pingouinux
Re : [RESOLU]Supprimer liens durs
Bonjour,
Le script rm_inodes_doubles.sh est à lancer depuis le répertoire où démarre la recherche. Il génère dans ce répertoire un fichier (fichier_a_verifier_puis_executer).
Ce script ne fait que générer un fichier, et ne touche à rien. Ce fichier, s'il est exécuté dans le répertoire de départ, conserve pour un même inode un des fichiers dont le nom comporte le moins de "/", et supprime les autres.
Il est bien entendu nécessaire de le vérifier avant de l'exécuter.
Remarque : Les noms de fichiers contenant des espaces sont gérés, mais pas ceux contenant des '\n'.
Remarque 2 : Ce script n'est pas très joli, et peut certainement être amélioré.
$ cat rm_inodes_doubles.sh
#!/bin/bash
find -type f -links +1 -print0 | xargs -0 ls -i | awk '
{ pos=index($0," ")+1; inod=$1;
n[inod]++;
c=0; for(k=pos;k<length($0);k++) {if (substr($0,k,1)=="/") c++}
n_slash[inod,n[inod]]=c
if(!min[inod]||(c<min[inod])) min[inod]=c
v[inod,n[inod]]=substr($0,pos);
ino[inod,n[inod]]=inod
}
END{
for( i in n) {
deja=0
for(k=1;k<=n[i];k++) {
if(deja) {
printf("rm %-50s # inode=%6s n_slash=%d\n","\""v[i,k]"\"",i,n_slash[i,k])
}
else {
if(n_slash[i,k]==min[ino[i,k]]) {
printf("#rm %-50s # inode=%6s n_slash=%d\n","\""v[i,k]"\"",i,n_slash[i,k])
deja=1
}
else {
printf("rm %-50s # inode=%6s n_slash=%d\n","\""v[i,k]"\"",i,n_slash[i,k])
}
}
}
}
}' >fichier_a_verifier_puis_executer
$ ./rm_inodes_doubles.sh
$ cat fichier_a_verifier_puis_executer
#rm "./a" # inode= 20 n_slash=1
rm "./tmp1/a 1" # inode= 20 n_slash=2
rm "./tmp1/a 2" # inode= 20 n_slash=2
rm "./tmp1/tmp2/aa 1" # inode= 20 n_slash=3
rm "./tmp1/tmp2/aa 2" # inode= 20 n_slash=3
rm "./tmp1/tmp2/www xxx " # inode= 20 n_slash=3
rm "./tmp1/tmp2/www yyy " # inode= 20 n_slash=3
#rm "./b" # inode= 21 n_slash=1
rm "./tmp1/bb" # inode= 21 n_slash=2
rm "./tmp1/tmp2/bb cc" # inode= 21 n_slash=3
Hors ligne
#18 Le 15/06/2012, à 16:01
- pingouinux
Re : [RESOLU]Supprimer liens durs
@credenhill #16 : Je n'ai vu ton message qu'après avoir envoyé le mien, et je me suis sans doute cassé la tête pour rien. Je ne connaissais pas cette possibilité du printf. J'aurais encore appris quelque chose.
Hors ligne
#19 Le 15/06/2012, à 16:14
- mixout
Re : [RESOLU]Supprimer liens durs
j'ai moi aussi avancé (pas aussi vite que vous cependant )
j'ai fait beaucoup de tri et je me suis aperçu qu'il y avait vraiment beaucoup de fichiers dont le nom comportait des
(1) des (2), des *(copie), etc.
tous ces fichiers "automatiquement" éffacés, il ne me reste plus que... 159 "doublons"
ça commence à devenir largement gérable, y compis par des
rm -i
@credenhill #16 : merci, ça fonctionne nickel mais je ne vais pas me servir de ça, l'organisation (ou plutot le foutoir !) de mes fichiers n'étant pas aussi claire que
un fichier + son lien dans un répertoire plus bas
enfin, c'est toujours vrai mais parfois cela ne m'arrange pas de supprimer le fichier "du bas"
un grand MERCI encore à vous, comme tu dis pingouinux, "J'aurais encore appris quelque chose"
Dernière modification par mixout (Le 15/06/2012, à 16:16)
#20 Le 15/06/2012, à 16:24
- credenhill
Re : [RESOLU]Supprimer liens durs
@pingouinux : il y a aussi une option -samefile fichier qui permet de retrouver tous les fichiers "liés durs" à un nom
@mixout: tu peux aussi générer une liste de tous les doublons dans un fichier, éditer ce fichier et placer rm devant ceux que tu veux enlever, et supprimer les autres lignes, et exécuter : sh ce_fichier
Hors ligne