查找目录中每个扩展名的文件数


10

我想计算目录中每个扩展名以及不带扩展名的文件的数量。

我已经尝试了一些选项,但是还没有找到可行的解决方案:

  • find "$folder" -type f | sed 's/.*\.//' | sort | uniq -c是一个选项,但如果没有文件扩展名则不起作用。我需要知道多少个文件没有扩展名。

  • 我也尝试过将find循环放入数组中,然后对结果求和,但是这时该代码引发未声明的变量错误,但仅在循环之外:

    declare -a arr
    arr=()
    echo ${arr[@]}
    

    这将引发未声明的变量,以及一旦查找循环完成。

Answers:


10
find "$path" -type f | sed -e '/.*\/[^\/]*\.[^\/]*$/!s/.*/(none)/' -e 's/.*\.//' | LC_COLLATE=C sort | uniq -c

说明:

  • find "$path" -type f 获取文件"$path"夹中所有文件的递归列表。
  • sed -e '/.*\/[^\/]*\.[^\/]*$/!s/.*/(none)/' -e 's/.*\.//' 常用表达:
    • /.*\/[^\/]*\.[^\/]*$/!s/.*/(none)/ 将所有不带扩展名的文件替换为(无)。
    • s/.*\.// 获取其余文件的扩展名。
  • LC_COLLATE=C sort 对结果进行排序,将符号放在顶部。
  • uniq -c 计算重复条目的数量。

9

使用Python:

import os
from collections import Counter
from pprint import pprint

lst = []
for file in os.listdir('./'):
        name, ext = os.path.splitext(file)
        lst.append(ext)

pprint(Counter(lst))

输出:

Counter({'': 7,
         '.png': 4,
         '.mp3': 3,
         '.jpg': 3,
         '.mkv': 3,
         '.py': 1,
         '.swp': 1,
         '.sh': 1})

您可能可以摆脱列表理解的ext = [ f.split('.')[-1] for f in os.listdir('./') ] 困扰,例如 Thatll使它的行数更短,甚至可能更Python化
Sergiy Kolodyazhnyy

感谢您的建议,我只是想尽我所能写清楚……
Ravexina

1
清晰是优点:)特别是在代码和工程文档方面。
Sergiy Kolodyazhnyy

6

如果您有GNU awk,则可以执行以下操作

printf '%s\0' * | gawk 'BEGIN{RS="\0"; FS="."; OFS="\t"} 
  {a[(NF>1 ? $NF : "(none)")]++} 
  END{for(i in a) print a[i],i}
'

例如,构造/增加在最后一个.分隔的字段上键入的关联数组,或者构造一些任意的固定字符串,例如(none)没有扩展名。

mawk似乎不允许使用空字节记录分隔符- mawk如果您确定不需要在文件名中处理换行符,则可以使用默认的换行符分隔符:

printf '%s\n' * | mawk 'BEGIN{FS="."; OFS="\t"} {a[(NF>1 ? $NF : "(none)")]++} END{for(i in a) print a[i],i}'

5

使用基本/bin/sh甚至bash是任务可能会有些困难,但是正如您在其他答案中所看到的那样,可用于聚合数据的工具可以非常轻松地处理此类任务。这样的工具之一就是sqlite数据库。

使用sqlite数据库的最简单过程是创建一个.csv具有两个字段的文件:文件名和扩展名。以后sqlite可以使用简单的聚合语句COUNT()GROUP BY ext基于扩展字段的文件计数

$ { printf "file,ext\n"; find -type f -exec sh -c 'f=${1##*/};printf "%s,%s\n" "${1}" "${1##*.}"' sh {} \; ; }  > files.csv
$ sqlite3 <<EOF
> .mode csv
> .import ./files.csv files_tb
> SELECT ext,COUNT(file) FROM files_tb GROUP BY ext;
> EOF
csv,1
mp3,6
txt,1
wav,27

files_tb我认为正在引用表,但未在任何可见的地方定义表列?
WinEunuuchs2Unix

@ WinEunuuchs2Unix它们是在csv文件本身中定义的。那就是第一个printf。并且SQLite将默认将csv文件的第一行作为列名。
Sergiy Kolodyazhnyy

1
非常令人印象深刻!+1
WinEunuuchs2Unix

5

如果可以的话,使用PowerShell

Get-ChildItem -File | Group-Object Extension -NoElement

或更短,使用别名:

ls -file | group -n Extension

1
哇!很棒的第一答案!我什至不知道PowerShell适用于Linux ... +1
Fabby

2
谢谢。它已经存在跨平台和开源已有一段时间了,但是在SO和SU上存在一种模式,其中Windows上有关shell脚本的问题通常用“嗯,安装cygwin并使用bash来回答,那么您可以执行以下操作”,因此我一直在犹豫是否要使用源自Windows的工具对Linux SE网站执行相同的操作。但这是一项不错的任务,可以很好地展示PowerShell的优势,而无需引起人们对冗长性的争论。
乔伊
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.