62 votes

Quelles sont les raisons pour lesquelles préférer glob à readdir (ou inversement) en Perl?

Cette question est un spin-off de cette une. Un peu d'histoire: lorsque j'ai appris Perl, j'ai toujours utilisé glob plutôt que d' opendir + readdir parce que je l'ai trouvé plus facile. Puis plus tard des postes divers et lectures suggérées qu' glob a été mauvais, et maintenant j'ai à peu près toujours utiliser readdir.

Après avoir réfléchi sur cette dernière question , j'ai réalisé que mes raisons pour l'un ou l'autre choix peuvent être superposés. Donc, je vais exposer le pour et le contre, et j'espère que les plus expérimentés Perl gens peuvent carillon et de clarifier. La question en un mot est il existe des raisons impérieuses de préférer glob de readdir ou readdir de glob (dans certains ou de tous les cas)?

glob pros:

  1. Pas de fichiers de configuration utilisateur (sauf si vous demandez pour eux)
  2. L'ordre des éléments est garanti
  3. Pas besoin de préfixer le nom du répertoire sur les éléments manuellement
  4. Meilleur nom (allez - glob contre readdir est pas contesté si nous avons de la à en juger par le nom seul)
  5. (À partir de ysth réponse; cf. glob contre 4 ci-dessous) Peut retourner inexistante noms de fichiers:

    @pont = glob "{A,K,Q,J,10,9,8,7,6,5,4,3,2}{\x{2660},\x{2665},\x{2666},\x{2663}}";

glob contre:

  1. Les anciennes versions sont tout simplement cassé (mais des "anciens" signifie avant 5.6, je crois, et franchement si vous êtes à l'aide de pré Perl 5.6, vous avez de plus gros problèmes)
  2. Appels stat à chaque fois (c'est à dire, inutile d'utiliser des stat dans la plupart des cas).
  3. Des problèmes avec les espaces dans les noms de répertoire (est-ce toujours le cas?)
  4. (À partir de brian de réponse) Peut retourner les noms de fichiers qui n'existent pas:

    perl -le 'impression glob "{ab}{cd}"'

readdir pros:

  1. (À partir de brian de réponse) opendir renvoie un descripteur de fichier que vous pouvez passer autour dans votre programme (et réutiliser), mais glob retourne simplement une liste
  2. (À partir de brian de réponse) readdir est un itérateur et propose des fonctions d' rewinddir, seekdir, telldir
  3. Plus vite? (Pure supposition basée sur certaines de glob'fonctions à partir de ci-dessus. Je ne suis pas vraiment inquiet à propos de ce niveau d'optimisation de toute façon, mais c'est théorique pro.)
  4. Moins sujettes à bord de cas de bugs qu' glob?
  5. Lit tout (dotfiles trop) par défaut (c'est aussi un con)
  6. Peut vous convaincre de ne pas le nom d'un fichier 0 (un con aussi - voir sa réponse)
  7. N'importe qui? Bueller? Bueller?

readdir contre:

  1. Si vous ne vous souvenez pas d'ajouter le nom de répertoire, vous permettra d' obtenir des bits lorsque vous essayez de faire filetests ou copier des éléments ou modifier des éléments ou...
  2. Si vous ne vous souvenez pas d' grep le . et .. articles, vous permettra d' obtenir peu, quand on compte les éléments, ou d'essayer de marcher de façon récursive en bas de l'arborescence de fichiers ou de...
  3. Ai-je mentionné les préfixant le nom du répertoire? (Une note, mais mon tout premier post du Perl Débutants de la liste de courrier était le classique, "Pourquoi est-ce code impliquant filetests fonctionne pas de temps en temps?" problème lié à cette chasse aux sorcières. Apparemment, je suis toujours amer.)
  4. Les articles sont retournés dans aucun ordre particulier. Cela signifie que vous devrez souvent n'oubliez pas de les trier, d'une certaine manière. (Ce pourrait être un pro si cela signifie plus de vitesse, et si cela signifie que vous fait réfléchir sur la façon et si vous avez besoin de trier les éléments.) Edit: Terrifiant petit échantillon, mais sur un Mac, readdir renvoie les éléments dans l'ordre alphabétique, insensible à la casse. Sur un système Debian et OpenBSD serveur, la commande est tout à fait aléatoire. J'ai testé le Mac avec Apple en Perl (5.8.8) et mon propre compilé 5.10.1. Le système Debian est 5.10.0, comme c'est la machine OpenBSD. Je me demande si c'est un problème de système de fichiers, plutôt que de Perl?
  5. Lit tout (dotfiles trop) par défaut (c'est aussi un pro)
  6. N'est pas forcément bien avec un fichier nommé 0 (voir les pros - voir sa réponse)

43voto

brian d foy Points 71781

Vous avez manqué le plus important, la plus grande différence entre eux: glob vous donne une liste, mais opendir vous donne un répertoire de la poignée. Vous pouvez passer ce répertoire autour de la poignée pour laisser à d'autres objets ou à des sous-programmes de l'utiliser. Avec l'annuaire de la poignée, la sous-routine ou de l'objet n'est pas de savoir quelque chose au sujet d'où il vient, qui d'autre l'utilise, et ainsi de suite:

 sub use_any_dir_handle {
      my( $dh ) = @_;
      rewinddir $dh;
      ...do some filtering...
      return \@files;
      }

Avec le dirhandle, vous avez une contrôlable itérateur où vous pouvez vous déplacer avec seekdir, mais avec des glob vous tout simplement obtenir l'élément suivant.

Comme avec tout, les coûts et les avantages n'ont de sens que lorsqu'il est appliqué à un certain contexte. Ils n'existent pas en dehors d'un usage particulier. Vous avez une excellente liste de leurs différences, mais je ne voudrais pas qualifier ces différences sans savoir ce que vous essayez de faire avec eux.

Quelques autres choses à retenir:

  • Vous pouvez implémenter votre propre glob avec opendir, mais pas l'inverse.

  • glob utilise sa propre syntaxe générique, et c'est tout ce que vous obtenez.

  • glob pouvez retourner les noms de fichiers qui n'existent pas:

    perl -le 'impression glob "{ab}{cd}"'

8voto

ysth Points 54757

glob pros: peuvent renvoyer des 'noms de fichiers' qui n'existent pas:

 @deck = glob "{A,K,Q,J,10,9,8,7,6,5,4,3,2}{\x{2660},\x{2665},\x{2666},\x{2663}}";
 

6voto

Brad Gilbert Points 12724

Ici, c'est un désavantage pour opendir et readdir.

{
  open my $file, '>', 0;
  print {$file} 'Breaks while( readdir ){ ... }'
}
opendir my $dir, '.';

my $a = 0;
++$a for readdir $dir;
print $a, "\n";

rewinddir $dir;

my $b = 0;
++$b while readdir $dir;
print $b, "\n";

Vous vous attendriez à ce code affiche le même nombre deux fois, mais ce n'est pas parce qu'il y a un fichier avec le nom de l' 0. Sur mon ordinateur, il imprime 251, et 188, testé avec Perl v5.10.0 et v5.10.1

Ce problème a également fait en sorte que cela imprime juste un tas de lignes vides, indépendamment de l'existence du fichier 0:

use 5.10.0;
opendir my $dir, '.';

say while readdir $dir;

Où, comme toujours, cela fonctionne très bien:

use 5.10.0;
my $a = 0;
++$a for glob '*';
say $a;

my $b = 0;
++$b while glob '*';
say $b;

say for glob '*';
say while glob '*';

Je fixe ces questions, et envoyé dans un patch qui fait en Perl v5.11.2, de sorte que cela fonctionne correctement avec Perl v5.12.0 d'où elle sort.

Mon fix convertit ce:

while( readdir $dir ){ ... }

dans ce:

while( defined( $_ = readdir $dir ){ ...}

Ce qui fait que cela fonctionne de la même manière qu' read a travaillé sur les fichiers. En fait c'est le même bout de code, j'ai juste ajouté un autre élément à la correspondante if des déclarations.

5voto

itub Points 303

glob facilite la lecture de tous les sous-répertoires d'une profondeur donnée, comme dans glob "*/*/*" . J'ai trouvé cela pratique à plusieurs reprises.

4voto

chaos Points 69029

Eh bien, vous le couvrez à peu près. Tout cela pris en compte, j'aurais tendance à utiliser glob lorsque je combinerai un script ponctuel rapide et que son comportement est exactement ce que je veux, et que j'utilise opendir et readdir dans le code de production en cours ou les bibliothèques où je peux prendre mon temps et plus clair, un code plus propre est utile.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X