Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#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 : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde 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 ? tongue


GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde 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 smile

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 wink


GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde 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 smile )

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" wink

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