linux - 获取不同的扩展名列表 Linux

标签 linux shell awk

我是 Linux 的新手,目前我遇到了一个问题。我想从文件夹中获取扩展名列表(.doc、.pdf)。我在谷歌上搜索了很多,最后我得到了下面给出的解决方案:

 find . -type f | awk -F. '!a[$NF]++{print $NF}'

我明白找到。 -type f,但无法理解 awk -F。 '!a[$NF]++{print $NF}' 是什么意思?

NF = 当前记录中的字段数

谁能解释一下?

提前致谢。

最佳答案

要回答您的问题,awk 行在做什么:

正如您已经指出的那样,行 find 。 -type f 返回位于当前目录中的文件列表。例如。

./foo.ext1
./bar.ext2
./spam.ext2
./ham.ext3
./spam.ham.eggs

此文件列表通过管道发送到命令 awk -F。 '!a[$NF]++{print $NF}'。这个 awk 行包含很多信息。首先你需要知道 awk 是一个记录解析器,其中每条记录由许多字段组成。默认记录是 line 而默认字段分隔符是空格序列。那么你的 awk 行现在做什么:

  • -F.::这将字段分隔符重新定义为点 (.)。从这一点开始,示例中的所有行现在都有 2 个字段(例如第 1 行 fooext1),而最后一行有 3 个字段(spam火腿鸡蛋)。
  • NF::这是一个 awk 变量,返回每条记录的字段数。很明显,扩展是用最后一个字段($NF)
  • 表示的
  • a[$NF]::这是一个数组,其中索引是扩展名。默认数组值为,除非您为其赋值。
  • a[$NF]++::这会返回 a[$NF] 的当前值,并在返回后将该值加 1。因此对于第 1 行,a["ext1"]++ 返回 0 并将 a["ext1"] 设置为 1。而对于第 3 行,a["ext2"]++ 返回 1 并将 a["ext2"] 设置为 2。这表示 a[$NF] 跟踪 $NF 出现的次数

  • !a[$NF]++::这结合了上述逻辑,但检查 a[$NF]++ 的返回值是 0。如果是0,返回true,否则返回false。对于示例的第 2 行,此语句将返回 true,因为 a["ext2"]++ 的值为 0 。但是,语句a["ext2"] 后的值为 1。当读取第 3 行时,该语句将返回 false。换句话说,我们已经看到 $NF 了吗?当您用"is"或“否”回答这个问题时,将 $NF 的计数加一。

  • !a[$NF]++{print $NF}::这结合了一切。它本质上指出,如果 !a[$NF]++ 返回 true,则 print $NF,但在打印增量 a[$NF] by one。 或者换句话说,如果表示扩展名 ($NF) 的字段第一次出现,则打印该字段。如果它之前已经出现过,什么都不做

数组的递增很重要,因为它跟踪已经看到的内容。所以逐行会发生以下情况

foo.ext1       => $NF="ext1", a["ext1"] is 0 so print $NF and set a["ext1"]=1
bar.ext2       => $NF="ext2", a["ext2"] is 0 so print $NF and set a["ext2"]=1
spam.ext2      => $NF="ext2", a["ext2"] is 1 so do not print and set a["ext2"]=2
ham.ext3       => $NF="ext3", a["ext3"] is 0 so print $NF and set a["ext3"]=1
spam.ham.eggs  => $NF="eggs", a["eggs"] is 0 so print $NF and set a["eggs"]=1

输出是

ext1
ext2
ext3
eggs

一般评论:

  • 隐藏目录中没有任何扩展名的文件(例如 ./path/to/awesome_filename_without_extension./path/to/.secret/filename_without_extension) 或其完整路径的一部分打印出来,就好像它是扩展名一样。然而,结果意义不大,即

    /path/to/awesome_filename_without_extension
    secret/awesome_filename_without_extension
    

    这最好解决为

    find . -type f -exec  basename -a '{}' + \
      | awk -F. '((NF>1)&&(!a[$NF]++)){print $NF}'
    

    此处 find 的输出直接由 basename 处理,它从文件名中剥离目录。 awk 行再检查一次,我们是否有超过 1 个字段(即是否有扩展名)。

关于linux - 获取不同的扩展名列表 Linux,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48635628/

相关文章:

java - 使用Eclipse执行脚本文件

shell - awk/sed 替换换行符

linux - 通过中间机器挂载远程文件系统(sshfs)

linux - Subversion 的预提交 Hook 失败

Android应用程序支持除android之外的所有平台

linux - 何时在 shell IF 条件下使用 -f 和 -z

linux - 使用 shell 脚本从特定日志文件创建 CSV 文件

bash - awk 格式化打印

linux - 我无法使用arm-none-eabi-gcc进行编译

linux - 无法在 Raspbian 上编译 iotivity 节点