使用名称上的特定字符串计算目录中的文件?

Luc*_*a O 20 bash

我有以下文件:

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
Run Code Online (Sandbox Code Playgroud)

我想计算snp名称中包含单词(区分大小写)的文件数量。我尝试使用

grep -a 'snp' | wc -l   
Run Code Online (Sandbox Code Playgroud)

但后来我意识到grep在文件中搜索。扫描文件名的正确命令是什么?

roa*_*ima 25

您的意思是要snp在文件名中搜索吗?那将是一个简单的 shell glob(通配符),像这样使用:

ls -dq *snp* | wc -l
Run Code Online (Sandbox Code Playgroud)

-q如果您的版本ls无法识别该标志,请忽略该标志。它处理包含“奇怪”字符(包括换行符)的文件名。

  • 请注意,如果返回的文件太多,这可能不起作用。 (2认同)

G-M*_*ca' 5

如果你静静地站在Unix&Linux的走廊上仔细聆听,你会听到一个鬼魅般的声音,凄厉的哀号:“文件名有换行怎么办?”

ls -d *snp* | wc -l
Run Code Online (Sandbox Code Playgroud)

或者,等效地

printf "%s\n" *snp* | wc -l
Run Code Online (Sandbox Code Playgroud)

将输出包含 的所有文件名snp,每个文件名后跟一个换行符, 但还包括文件名中的任何换行符,然后计算输出中的行数。如果有一个文件名是

                                f o o s n p \n b a r . t s v

那么这个名字将被写成

foosnp
bar.tsv
Run Code Online (Sandbox Code Playgroud)

当然,这将被算作两行。

有一些替代方案至少在某些情况下效果更好:

printf "%s\n" * | grep -c snp
Run Code Online (Sandbox Code Playgroud)

它计算包含 的行snp,所以foosnp(\n)bar.tsv上面的例子只计算一次。对此略有不同的是

ls -f | grep -c snp
Run Code Online (Sandbox Code Playgroud)

上述两个命令的不同之处在于:

  • ls -f将包括文件名称开头.; 对printf … *不对,除非dotglob外壳选项设置。
  • printf是一个内置的 shell;ls是外部命令。因此,ls可能会使用更多的资源。
  • 当 shell 处理 a 时*,它会对文件名进行排序; ls -f不对文件名进行排序。因此,ls可能会使用较少的资源。

但它们有一些共同点:当文件名包含换行符并且snp在换行符前后都有时,它们都会给出错误的结果。

其他:

filenamelist=(*snp*)
echo ${#filenamelist[@]}
Run Code Online (Sandbox Code Playgroud)

这将创建一个 shell 数组变量,列出包含 的所有文件名,snp然后报告数组中的元素数。文件名被视为字符串,而不是行,因此嵌入的换行符不是问题。可以想象,如果目录很大,这种方法可能会出现问题,因为文件名列表必须保存在 shell 内存中。

完后还有:

早些时候,当我们说 时printf "%s\n" *snp*,该printf命令"%s\n"为 的扩展中的每个参数重复(重用)一次格式字符串*snp*。在这里,我们做了一个小改动:

printf "%.0s\n" *snp* | wc -l
Run Code Online (Sandbox Code Playgroud)

这将为."%.0s\n"扩展中的每个参数重复(重用)格式字符串一次*snp*。但是"%.0s"意味着打印每个字符串的前零个字符——即,什么也不打印。该printf命令将只输出一个包含snp在其名称中的文件的换行符(即空行);然后wc -l会计算它们。同样,您可以.通过设置包含文件dotglob