Quelle longueur? Longueur du nom de fichier? Longueur de page?
Ignacio Vazquez-Abrams
Réponses:
18
En supposant que vous utilisez GNU find(ce que vous êtes probablement, car -iregexc'est une extension GNU pour POSIXfind ), -regexet -iregexpar défaut pour les expressions régulières Emacs, qui ne reconnaissent pas {3,}. Vous devez spécifier un type différent d'expressions régulières à l'aide de l' -regextypeoption; en outre, vous devez ajuster votre expression régulière au fait que l'expression correspond au chemin complet:
Pour être complet, avec FreeBSD ou NetBSD find(une autre implémentation qui prend en charge -iregex, pas la vôtre, car .+cela ne fonctionnerait pas sans -E), vous écririez:
find ~ -iregex '.*[^/]\{3\}\.pdf'
ou:
find -E ~ -iregex '.*[^/]{3}\.pdf'
Sans -E, c'est une expression régulière de base (comme dans grep) et avec -Eune expression régulière étendue (comme dans grep -E).
Ici, c'est plus facile avec les caractères génériques standard:
find ~ -name '*???.[pP][dD][fF]'
Ou avec certaines findimplémentations (celles qui prennent en -regexcharge prennent également en charge -iname):
find ~ -iname '*???.pdf'
Pour des nombres arbitraires de caractères au lieu de 3, c'est là que vous préférerez peut-être revenir à l' -iregexendroit où ils sont disponibles (voir la réponse de @Stephen Kitt ) ou vous pouvez utiliser zshou ksh93globs:
zsh:
set -o extendedglob # best in ~/.zshrc
printf '%s\n' ~/**/?(#c3,).(#i)pdf(D)
(le (D)pour considérer les fichiers cachés et les fichiers dans des répertoires cachés comme avec find)
(#cx,y)est l' zshéquivalent générique de l'expression rationnelle{x,y}
(#i) insensible à la casse
?caractère générique standard pour tout caractère unique (comme l'expression régulière .)
**/: tout niveau de sous-répertoires (dont 0)
ksh93:
FIGNORE='@(.|..)' # to consider hidden files
set -o globstar
printf '%s\n' **/{3,}(?).~(i:pdf)
@(x|y): opérateur générique ksh étendu similaire à l'expression rationnelle (x|y).
FIGNORE: variable spéciale qui contrôle quels fichiers sont ignorés par les globes. Lorsqu'il est défini, l'ignorance habituelle des fichiers cachés n'est pas effectuée, mais nous voulons toujours ignorer les entrées du répertoire .et ..là où elles sont présentes.
{x,y}(z)est ksh93l'équivalent de regexp z{x,y}.
~(i:...): correspondance insensible à la casse.
Les globes ont quelques avantages supplémentaires findici dans la mesure où vous obtenez une liste triée (vous pouvez désactiver ce tri zshavec le oNqualificatif glob ou utiliser différents critères de tri) et également fonctionner lorsque les noms de fichiers contiennent une séquence d'octets qui ne forment pas de caractères valides (pour Par exemple, dans un environnement local utilisant le jeu de caractères UTF-8, l' findapproche échouerait à signaler un $'St\xE9phane Chazelas - CV.pdfcar ce \xE9n'est pas un caractère qui ne correspond pas à l'expression rationnelle .ou au caractère générique ?ou *à GNU find).
Est-ce que cela fonctionnerait pour Bash? shopt -s dotglob globstar; printf '%s\n' ~/**/*???.[pP][dD][fF]
wjandrea
7
Comment savoir si ce sont des PDF?
Vous ne le faites pas sauf si vous le demandez. Bien sûr, je suis pédant, mais vous n'avez pas posé de questions sur les fichiers avec .pdfleur nom . Le fait qu'un fichier ait des caractères .pdfdans le nom de fichier n'en fait pas un fichier PDF .
En fait, soyons pédant à ce sujet: si les quatre derniers caractères du nom d'un fichier le sont .pdf, il aura toujours plus de trois caractères dans son nom .
Donc, en faisant cela dans le mauvais sens , vous pourriez dire:
Vous voyez ce deuxième? C'est en fait un exécutable. (Je sais, j'ai changé le nom.) Et il me manque aussi un PDF que je pourrais jurer être dans le répertoire Documents ...
$ ls Documents
McLaren 720s Coupe:Order Summary.pdf
Pioneer Premier DEH-P490IB CD Install Manual.PDF
Setup_MagicISO.exe.pdf
Donc, en utilisant, -inamenous pourrions trouver celui-là, mais cela continue de générer ce fichier non PDF.
Ce que nous voulons vraiment faire dans ce cas, c'est examiner le nombre magique du fichier à l' aide de la filecommande. Une option génère le type MIME , qui est plus simple à analyser. La findrequête devient alors simple -name "???*".
Utilisons le délimiteur deux-points, recherchons le type MIME application/pdf, puis remettons à zéro cette partie et imprimons le résultat. Prenez note, un de mes fichiers a un deux-points dans le nom; donc je ne peux pas demander à awk ($2==":"){print $1}.
$ find . -type f -name "???*" -print0|xargs -0 file --mime|awk -F: '($NF~"application/pdf"){OFS=":";$NF="";print}'|sed s/:$//
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Pioneer Premier DEH-P490IB CD Install Manual.PDF
Terminons maintenant en essayant d'inclure les fichiers PDF nommés aet abc:
$ mkdir Documents/other
$ cp -a Documents/McLaren\ 720s\ Coupe\:Order\ Summary.pdf Documents/other/a
$ cp -a Documents/Pioneer\ Premier\ DEH-P490IB\ CD\ Install\ Manual.PDF Documents/other/abc
$ find . -type f -name "???*" -print0|xargs -0 file --mime|awk -F: '($NF~"application/pdf"){OFS=":";$NF="";print}'|sed s/:$//
./Documents/McLaren 720s Coupe:Order Summary.pdf
./Documents/Pioneer Premier DEH-P490IB CD Install Manual.PDF
./Documents/other/abc
C'est tout. Je sais que je serai probablement fatigué d'être horriblement pédant, mais dans mon travail avec des milliers de volumes NFS à chasser et toutes sortes de fichiers mal nommés, je souhaite que plus de gens soient pédants.
Modifié pour ajouter: dans le monde réel, je pourrais vouloir utiliser updatedbpour construire un index de fichier consultable, locateau lieu de findlire cet index, et parallelau lieu de l' xargsenfiler. C'est quelque peu en dehors de la portée de cette question. J'ai aussi écrit ça avec un visage impassible. Pourquoi je m'en soucie autant? Je recherche peut-être des films et des fichiers audio; ou certains types de photographies; ou exécutables binaires dans un répertoire de données de projet.
Si le demandeur a la même situation que vous, où il y a des fichiers PDF dont les noms ne se terminent pas .pdf, alors votre pédanterie sera très appréciée. Mais c'est une situation relativement inhabituelle (malgré votre travail) et nous n'avons aucune raison de croire que le demandeur doit réellement y faire face, donc je pense que l'argument que vous faites, bien que valide, est un peu distrayant - et je pense que la façon énergique que vous avez formulée pousse la réponse dans le domaine du "(probablement) pas utile". (Mon opinion seulement, bien sûr.)
David Z
Puisque nous sommes pédant, comment géreriez- vous les fichiers PDF tels que les polyglottes PoC || GTFO ?
Stephen Kitt
@StephenKitt - Je ne sais pas ce que vous demandez, mais je suis intrigué. Ils ressemblent à des PDF ordinaires avec des noms pas particulièrement géniaux. Est-ce que cela échouerait ma solution suggérée?
Rich
@DavidZ Je ne sais pas quoi dire à cela. Je veux dire, n'est-ce pas un peu pédant de souligner que je suis pédant alors que j'en ai déjà dit autant? Voici pourquoi ce n'est "pas utile": une bonne solution pour trouver des PDF devrait être une solution adaptable pour trouver des scripts, des exécutables binaires, des bibliothèques, des fichiers multimédias, etc. Je ne peux même pas commencer à voir comment j'adapterais l'un des d'autres réponses pour "exécutables compressés Mach", mais je suis prêt à apprendre.
Rich
1
@ Beaucoup de fichiers PDF sont également des fichiers ZIP, certains sont également des images ou même des machines virtuelles amorçables ... (Voir les liens «spoilers» sur les premiers numéros pour des conseils; le reste est documenté dans les PDF eux-mêmes.)
Réponses:
En supposant que vous utilisez GNU
find
(ce que vous êtes probablement, car-iregex
c'est une extension GNU pour POSIXfind
),-regex
et-iregex
par défaut pour les expressions régulières Emacs, qui ne reconnaissent pas{3,}
. Vous devez spécifier un type différent d'expressions régulières à l'aide de l'-regextype
option; en outre, vous devez ajuster votre expression régulière au fait que l'expression correspond au chemin complet:Vous devez également échapper au
.
afin qu'il corresponde à "." plutôt que n'importe quel caractère:L'expression régulière peut être simplifiée car nous ne nous soucions que de trois caractères non «/»:
Pour être complet, avec FreeBSD ou NetBSD
find
(une autre implémentation qui prend en charge-iregex
, pas la vôtre, car.+
cela ne fonctionnerait pas sans-E
), vous écririez:ou:
Sans
-E
, c'est une expression régulière de base (comme dansgrep
) et avec-E
une expression régulière étendue (comme dansgrep -E
).Avec ast-open
find
:(c'est regexps étendu hors de la boîte).
la source
Ici, c'est plus facile avec les caractères génériques standard:
Ou avec certaines
find
implémentations (celles qui prennent en-regex
charge prennent également en charge-iname
):Pour des nombres arbitraires de caractères au lieu de
3
, c'est là que vous préférerez peut-être revenir à l'-iregex
endroit où ils sont disponibles (voir la réponse de @Stephen Kitt ) ou vous pouvez utiliserzsh
ouksh93
globs:zsh
:(le
(D)
pour considérer les fichiers cachés et les fichiers dans des répertoires cachés comme avecfind
)(#cx,y)
est l'zsh
équivalent générique de l'expression rationnelle{x,y}
(#i)
insensible à la casse?
caractère générique standard pour tout caractère unique (comme l'expression régulière.
)**/
: tout niveau de sous-répertoires (dont 0)ksh93
:@(x|y)
: opérateur générique ksh étendu similaire à l'expression rationnelle(x|y)
.FIGNORE
: variable spéciale qui contrôle quels fichiers sont ignorés par les globes. Lorsqu'il est défini, l'ignorance habituelle des fichiers cachés n'est pas effectuée, mais nous voulons toujours ignorer les entrées du répertoire.
et..
là où elles sont présentes.{x,y}(z)
estksh93
l'équivalent de regexpz{x,y}
.~(i:...)
: correspondance insensible à la casse.Les globes ont quelques avantages supplémentaires
find
ici dans la mesure où vous obtenez une liste triée (vous pouvez désactiver ce trizsh
avec leoN
qualificatif glob ou utiliser différents critères de tri) et également fonctionner lorsque les noms de fichiers contiennent une séquence d'octets qui ne forment pas de caractères valides (pour Par exemple, dans un environnement local utilisant le jeu de caractères UTF-8, l'find
approche échouerait à signaler un$'St\xE9phane Chazelas - CV.pdf
car ce\xE9
n'est pas un caractère qui ne correspond pas à l'expression rationnelle.
ou au caractère générique?
ou*
à GNUfind
).la source
shopt -s dotglob globstar; printf '%s\n' ~/**/*???.[pP][dD][fF]
Comment savoir si ce sont des PDF?
Vous ne le faites pas sauf si vous le demandez. Bien sûr, je suis pédant, mais vous n'avez pas posé de questions sur les fichiers avec
.pdf
leur nom . Le fait qu'un fichier ait des caractères.pdf
dans le nom de fichier n'en fait pas un fichier PDF .En fait, soyons pédant à ce sujet: si les quatre derniers caractères du nom d'un fichier le sont
.pdf
, il aura toujours plus de trois caractères dans son nom .Donc, en faisant cela dans le mauvais sens , vous pourriez dire:
Vous voyez ce deuxième? C'est en fait un exécutable. (Je sais, j'ai changé le nom.) Et il me manque aussi un PDF que je pourrais jurer être dans le répertoire Documents ...
Donc, en utilisant,
-iname
nous pourrions trouver celui-là, mais cela continue de générer ce fichier non PDF.Ce que nous voulons vraiment faire dans ce cas, c'est examiner le nombre magique du fichier à l' aide de la
file
commande. Une option génère le type MIME , qui est plus simple à analyser. Lafind
requête devient alors simple-name "???*"
.Utilisons le délimiteur deux-points, recherchons le type MIME
application/pdf
, puis remettons à zéro cette partie et imprimons le résultat. Prenez note, un de mes fichiers a un deux-points dans le nom; donc je ne peux pas demander à awk($2==":"){print $1}
.Terminons maintenant en essayant d'inclure les fichiers PDF nommés
a
etabc
:C'est tout. Je sais que je serai probablement fatigué d'être horriblement pédant, mais dans mon travail avec des milliers de volumes NFS à chasser et toutes sortes de fichiers mal nommés, je souhaite que plus de gens soient pédants.
Modifié pour ajouter: dans le monde réel, je pourrais vouloir utiliser
updatedb
pour construire un index de fichier consultable,locate
au lieu defind
lire cet index, etparallel
au lieu de l'xargs
enfiler. C'est quelque peu en dehors de la portée de cette question. J'ai aussi écrit ça avec un visage impassible. Pourquoi je m'en soucie autant? Je recherche peut-être des films et des fichiers audio; ou certains types de photographies; ou exécutables binaires dans un répertoire de données de projet.la source
.pdf
, alors votre pédanterie sera très appréciée. Mais c'est une situation relativement inhabituelle (malgré votre travail) et nous n'avons aucune raison de croire que le demandeur doit réellement y faire face, donc je pense que l'argument que vous faites, bien que valide, est un peu distrayant - et je pense que la façon énergique que vous avez formulée pousse la réponse dans le domaine du "(probablement) pas utile". (Mon opinion seulement, bien sûr.)