J'ai les fichiers suivants:
Codigo-0275_tdim.matches.tsv
Codigo-0275_tdim.snps.tsv
FloragenexTdim_haplotypes_SNp3filter17_single.tsv
FloragenexTdim_haplotypes_SNp3filter17.tsv
FloragenexTdim_SNP3Filter17.fas
S134_tdim.alleles.tsv
S134_tdim.snps.tsv
S134_tdim.tags.tsv
Je veux compter le nombre de fichiers qui ont le mot snp
(sensible à la casse) sur leur nom. J'ai essayé d'utiliser
grep -a 'snp' | wc -l
mais j'ai réalisé que les grep
recherches dans les fichiers. Quelle est la bonne commande pour parcourir les noms de fichiers?
Réponses:
Voulez-vous dire que vous souhaitez rechercher
snp
dans les noms de fichiers ? Ce serait un simple shell glob (joker), utilisé comme ceci:Omettez le
-q
drapeau si votre version dels
ne le reconnaît pas. Il gère les noms de fichiers contenant des caractères "étranges" (y compris les retours à la ligne).la source
ls
pour récupérer les noms de fichiers contenant du texte spécifique. Cela a fonctionné cependant, merci.ls
qui correspond aux noms de fichiers, c'est le shell.ls
voit une liste de fichiers correspondant au modèle; il ne voit pas le motif lui-même.Si vous vous tenez tranquillement dans les couloirs d'Unix et Linux et écoutez attentivement, vous entendrez une voix fantomatique, gémissant pitoyablement, «Et les noms de fichiers qui contiennent des sauts de ligne?»
ou, de manière équivalente ,
affichera tous les noms de fichiers qui contiennent
snp
, chacun suivi d'un retour à la ligne, mais également tous les retours à la ligne dans les noms de fichiers , puis comptera le nombre de lignes dans la sortie. S'il existe un fichier dont le nom estf o o s n p \n b a r . t s v
alors ce nom sera écrit comme
qui, bien sûr, comptera pour deux lignes.
Il existe quelques alternatives qui font mieux dans au moins certains cas:
qui compte les lignes qui contiennent
snp
, donc l'foosnp(\n)bar.tsv
exemple ci-dessus ne compte qu'une seule fois. Une légère variation à ce sujet estLes deux commandes ci-dessus diffèrent en ce que:
ls -f
comprendra des fichiers dont les noms commencent par.
; ceprintf … *
n'est pas le cas, sauf si l'dotglob
option shell est définie.printf
est un shell intégré;ls
est une commande externe. Par conséquent, lels
peut utiliser un peu plus de ressources.*
, il trie les noms de fichiers;ls -f
ne trie pas les noms de fichiers. Par conséquent, lels
peut utiliser un peu moins de ressources.Mais ils ont quelque chose en commun: ils donneront tous les deux des résultats erronés en présence de noms de fichiers qui contiennent un retour à la ligne et qui ont à la
snp
fois avant et après le retour à la ligne .Un autre:
Cela crée une variable de tableau shell répertoriant tous les noms de fichiers qui contiennent
snp
, puis signale le nombre d'éléments dans le tableau. Les noms de fichiers sont traités comme des chaînes, pas comme des lignes, donc les sauts de ligne intégrés ne sont pas un problème. Il est concevable que cette approche puisse avoir un problème si le répertoire est énorme, car la liste des noms de fichiers doit être conservée dans la mémoire du shell.Encore un autre:
Plus tôt, lorsque nous l'avons dit
printf "%s\n" *snp*
, laprintf
commande a répété (réutilisé) la"%s\n"
chaîne de formatage une fois pour chaque argument dans l'expansion de*snp*
. Ici, nous faisons un petit changement:Cela va répéter (réutiliser) la
"%.0s\n"
chaîne de formatage une fois pour chaque argument dans l'expansion de*snp*
. Mais"%.0s"
signifie imprimer les premiers caractères zéro de chaque chaîne - c'est-à-dire rien. Cetteprintf
commande ne produira qu'une nouvelle ligne (c'est-à-dire une ligne vierge) pour chaque fichier qui contientsnp
son nom; puiswc -l
les comptera. Et, encore une fois, vous pouvez inclure les.
fichiers en définissantdotglob
.la source
Abstrait:
Fonctionne pour les fichiers avec des noms "impairs" (y compris les nouvelles lignes).
La description
Comme un simple glob correspondra à chaque nom de fichier avec
snp
dans son nom, un simpleecho *snp*
pourrait suffire dans ce cas, mais pour vraiment montrer qu'il n'y a que trois fichiers correspondant, je vais utiliser:Le seul problème qui reste est de compter les fichiers. Oui, grep est une solution habituelle, et oui, compter de nouvelles lignes avec
wc -l
est également une solution habituelle. Notez quegrep -c
(count) compte vraiment combien de fois unesnp
chaîne est mise en correspondance et, si un nom de fichier a plus d'unesnp
chaîne dans le nom, le nombre sera incorrect.On peut faire mieux.
Une solution simple consiste à définir les arguments positionnels:
Pour éviter de changer les arguments positionnels, nous pouvons transformer chaque argument en un caractère et afficher la longueur de la chaîne résultante (pour la plupart des shells):
Ou, en bash, pour éviter un sous-shell:
Liste des fichiers
Liste des fichiers (de la question d'origine avec un avec une nouvelle ligne ajoutée):
Cela aura un fichier avec une nouvelle ligne au milieu:
f o o s n p \n b a r . t s v
Et pour tester l'expansion globale:
Cela ajoutera un astérisque qui, s'il n'est pas cité, s'étendra à toute la liste des fichiers.
la source
disons que vous vouliez compter le nombre de fichiers html:
donc si vous comptez les occurrences de "snp":
la source