1 votes

Mettre en évidence plusieurs PDF dans un même dossier

J'ai besoin de trouver chaque dossier contenant plus d'un PDF dans une structure de dossiers mais en cachant les fichiers cachés tels que .HResource qui s'infiltrent dans notre système de fichiers.

Je veux seulement filtrer les dossiers qui ont HiRes dans le nom de fichier.

Idéalement, je veux exécuter cette opération au niveau supérieur pour qu'elle recherche chaque dossier avec HiRes et qu'elle rejette les dossiers contenant plus d'un PDF.

Le système d'exploitation est RHEL 7 et cette commande peut être exécutée en tant qu'utilisateur/root si nécessaire.

Je me suis amusé avec

find -type f -iname '*.pdf' -iname '*HiRes*' ! -iname '.*' -printf '%h\n' | sort | uniq -d

mais j'ai eu très peu de chance jusqu'à présent, car les fichiers cachés continuent de s'afficher, ce qui donne des milliers de faux positifs dans un système de 11 000 dossiers. Par exemple, avec la structure de répertoire suivante,

.
|--Apples.HiRes1
|     |--Gala.pdf
|     |--Granny Smith.pdf
|     |--McIntosh.pdf
|     |--Red Delicious.pdf
|--Banana-HiRes2
|     |--upper.pdf
|     |--subdir
|     |    |--lower.pdf
|--Cherry_HiRes3
|     |--Bing.pdf
|     |--Blossom.jpg
|     |--.pesky
|     |--.hidden
|     |--.files
|     |--.HResource
|--Dates (HiRes4)
|     |--Midsummer.Pdf
|     |--New Year’s Eve.PDF
|--Employees
|     |--Fred.pdf
|     |--Ginger.pdf
|     |--New Hires
|     |     |--Sam Malone.pdf
|     |     |--Woody Boyd.pdf
|--Gemstones
|     |--Rubies
|     |     |--1.pdf
|     |     |--2.pdf
|     |--Sapphires
|     |     |--3.pdf
|     |     |--4.pdf
|--Tomato.HiRes
|     |--Bacon
|     |--Lettuce
|     |     |--5.pdf
|     |     |--6.pdf
|--Zucchini.LoRes
|     |--Bread.pdf
|     |--Squash.pdf

la sortie devrait être

./Apples.HiRes1
./Dates (HiRes4)

Notez que

  • Cherry_HiRes3 est exclu car il ne contient qu'un seul fichier PDF.
  • Banana-HiRes2 et Tomato.HiRes sont exclus parce qu'ils ont deux fichiers PDF sous mais pas sur les.
  • Zucchini.LoRes est exclu (évidemment) parce que son nom a LoRes plutôt que HiRes .

0voto

Skudd Points 121

EDITAR : En fait, cela ne fonctionne pas non plus. Voir les commentaires ci-dessous.


Avez-vous essayé d'ajouter -not -iname '.*' à votre find commande ? Le site ! ne fait probablement pas ce que vous pensez.

Il en résulterait find -type f -iname '*.pdf' -iname 'HiRes' -not -iname '.*' -printf '%h\n' | sort | uniq -d

0voto

Une solution proche de ce que vous avez essayé est

find . -ipath '*HiRes*/*.pdf' -printf '%h\n' | sort | uniq -d

Comme vous semblez le comprendre (au moins partiellement), le site -name et  -iname les tests ne fonctionnent que sur un seul nom de fichier ; c'est-à-dire un seul niveau d'un nom de chemin.  Ainsi, lorsque vous dites -iname '*.pdf' -iname '*HiRes*' , c'est l'équivalent de -iname '*HiRes*.pdf' ; c'est-à-dire que vous recherchez des fichiers dont le nom correspond aux deux critères suivants *.pdf et  *HiRes* .  Cependant, le -path , -ipath , -regex et -iregex tests opèrent sur l'ensemble du chemin, donc cela liste les fichiers dont le chemin contient HiRes et se termine par  .pdf .  Nous avons mis un / entre eux pour s'assurer que le HiRes est dans un nom de répertoire, donc on ne trouve pas de fichiers appelés abcHiRes123.pdf .

On peut faire exactement la même chose avec

find . -iregex '.*HiRes.*/.*\.pdf' -printf '%h\n' | sort | uniq –d

Notez la différence entre la syntaxe glob (telle qu'utilisée par  -ipath ) et la syntaxe des regex.  Point ( . ) signifie n'importe quel caractère, nous devons donc utiliser .* pour correspondre à "n'importe quoi". et  \. pour correspondre à une valeur littérale . .

Dans les deux cas, on trouvera le Tomato.HiRes répertoire dans l'exemple de votre question, parce que .  correspond à  / donc .*/.* correspond à /Lettuce/5 , donc .*HiRes.*/.*\.pdf correspond à ./Tomato.HiRes/Lettuce/5.pdf .  Si cela vous convient, tant mieux.  Mais, si vous voulez compter seulement les fichiers PDF qui sont sur*HiRes utilisez

find . -iregex '.*HiRes[^/]*/[^/]*\.pdf' -printf '%h\n' | sort | uniq -d

dans laquelle nous utilisons [^/] pour correspondre à tout caractère autre qu'un / .


Une approche sensiblement différente, qui peut être plus facile à comprendre, est la suivante

find . -iname '*HiRes*' -type d -exec sh -c \
                    'shopt -s nocaseglob; for dir do files=("$dir"/*.pdf);
                    if [ "${#files[@]}" -gt 1 ]; then echo "$dir"; fi; done' sh {} +

Cela n'utilise que find pour trouver des répertoires appelés *HiRes* .  Il transmet ensuite ces noms de répertoire à un court Shell Shell, qui utilise glob pour énumérer tous les fichiers PDF dans chaque répertoire et les compter.

-1voto

Skudd Points 121

Ok, j'ai donné un autre coup de couteau après avoir réalisé que ma réponse précédente était fausse. JandP, vous êtes si près d'avoir la bonne commande.


La mise en place

  • 10 répertoires, de 1 à 10, appelés $s voici
  • $n dans chacun d'eux, où $n est le numéro du répertoire, nommé $s-$n.pdf
  • $n dotfiles dans chacun, .fake-$s-$n.pdf

Commande que j'ai utilisée pour créer cette arborescence de fichiers : for s in `seq 1 10`; do mkdir $s; cd $s; for n in `seq 1 $s`; do touch $s-$n.pdf; touch .fake-$s-$n.pdf; done; cd ..; done

Il a produit cet arbre :

.
 1
    1-1.pdf
    .fake-1-1.pdf
 10
    10-10.pdf
    10-1.pdf
    10-2.pdf
    10-3.pdf
    10-4.pdf
    10-5.pdf
    10-6.pdf
    10-7.pdf
    10-8.pdf
    10-9.pdf
    .fake-10-10.pdf
    .fake-10-1.pdf
    .fake-10-2.pdf
    .fake-10-3.pdf
    .fake-10-4.pdf
    .fake-10-5.pdf
    .fake-10-6.pdf
    .fake-10-7.pdf
    .fake-10-8.pdf
    .fake-10-9.pdf
 2
    2-1.pdf
    2-2.pdf
    .fake-2-1.pdf
    .fake-2-2.pdf
 3
    3-1.pdf
    3-2.pdf
    3-3.pdf
    .fake-3-1.pdf
    .fake-3-2.pdf
    .fake-3-3.pdf
 4
    4-1.pdf
    4-2.pdf
    4-3.pdf
    4-4.pdf
    .fake-4-1.pdf
    .fake-4-2.pdf
    .fake-4-3.pdf
    .fake-4-4.pdf
 5
    5-1.pdf
    5-2.pdf
    5-3.pdf
    5-4.pdf
    5-5.pdf
    .fake-5-1.pdf
    .fake-5-2.pdf
    .fake-5-3.pdf
    .fake-5-4.pdf
    .fake-5-5.pdf
 6
    6-1.pdf
    6-2.pdf
    6-3.pdf
    6-4.pdf
    6-5.pdf
    6-6.pdf
    .fake-6-1.pdf
    .fake-6-2.pdf
    .fake-6-3.pdf
    .fake-6-4.pdf
    .fake-6-5.pdf
    .fake-6-6.pdf
 7
    7-1.pdf
    7-2.pdf
    7-3.pdf
    7-4.pdf
    7-5.pdf
    7-6.pdf
    7-7.pdf
    .fake-7-1.pdf
    .fake-7-2.pdf
    .fake-7-3.pdf
    .fake-7-4.pdf
    .fake-7-5.pdf
    .fake-7-6.pdf
    .fake-7-7.pdf
 8
    8-1.pdf
    8-2.pdf
    8-3.pdf
    8-4.pdf
    8-5.pdf
    8-6.pdf
    8-7.pdf
    8-8.pdf
    .fake-8-1.pdf
    .fake-8-2.pdf
    .fake-8-3.pdf
    .fake-8-4.pdf
    .fake-8-5.pdf
    .fake-8-6.pdf
    .fake-8-7.pdf
    .fake-8-8.pdf
 9
     9-1.pdf
     9-2.pdf
     9-3.pdf
     9-4.pdf
     9-5.pdf
     9-6.pdf
     9-7.pdf
     9-8.pdf
     9-9.pdf
     .fake-9-1.pdf
     .fake-9-2.pdf
     .fake-9-3.pdf
     .fake-9-4.pdf
     .fake-9-5.pdf
     .fake-9-6.pdf
     .fake-9-7.pdf
     .fake-9-8.pdf
     .fake-9-9.pdf

10 directories, 110 files

La recherche

En utilisant la méthode de base de JandP find et les connaissances révélées dans les commentaires de mon autre réponse (incorrecte), a produit une sortie montrant le nombre de fichiers correspondants dans chaque répertoire, à l'exclusion de tous les dotfiles :

$ find -type f -iname '*.pdf' ! -iname '.*' -printf '%h\n' | sort | uniq -c
      1 ./1
     10 ./10
      2 ./2
      3 ./3
      4 ./4
      5 ./5
      6 ./6
      7 ./7
      8 ./8
      9 ./9

En lançant un simple awk comparaison sur la fin, a produit le résultat attendu :

$ find -type f -iname '*.pdf' ! -iname '.*' -printf '%h\n' | sort | uniq -c | awk '$1 > 1'
     10 ./10
      2 ./2
      3 ./3
      4 ./4
      5 ./5
      6 ./6
      7 ./7
      8 ./8
      9 ./9

La conclusion

JandP était si proche. Cette réponse a nécessité un peu de Google-fu, mais s'est imposée assez facilement à partir de là. Je vous recommande d'étudier ce scénario et cette réponse, et de les appliquer à votre situation actuelle. Ensuite, démontez-les. Comprenez ce que fait chaque commande, pourquoi les arguments sont formulés de cette manière et quel est le résultat produit. Apprenez pourquoi le fait de les combiner a le comportement qu'il a. Cela vous mènera loin dans votre carrière d'administrateur système.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X