获取不同的扩展列表Linux
我是Linux新手,目前面临一个问题。我想从文件夹中获取扩展名列表(.doc、.pdf)。我在谷歌上搜索了很多,最后我得到了一个解决方案,如下所示:获取不同的扩展列表Linux,linux,shell,awk,Linux,Shell,Awk,我是Linux新手,目前面临一个问题。我想从文件夹中获取扩展名列表(.doc、.pdf)。我在谷歌上搜索了很多,最后我得到了一个解决方案,如下所示: find . -type f | awk -F. '!a[$NF]++{print $NF}' 我理解find-键入f,但无法理解awk-f![$NF]+{print$NF}'这是什么意思 NF=当前记录中的字段数 有人能解释一下吗 提前感谢。为此,您可以使用以下命令: $find <DIR> -type f -print0 | x
find . -type f | awk -F. '!a[$NF]++{print $NF}'
我理解find-键入f,但无法理解awk-f![$NF]+{print$NF}'
这是什么意思
NF=当前记录中的字段数
有人能解释一下吗
提前感谢。为此,您可以使用以下命令:
$find <DIR> -type f -print0 | xargs -0 -n1 basename | grep -Po '(?<=.)\..*$' | sort | uniq
.bak
.c
.file
.file.bak
.input
.input.bak
.log
.log.bak
.out
.out.bak
.test
.test.bak
.txt
.txt.bak
为此,可以使用以下命令:
$find <DIR> -type f -print0 | xargs -0 -n1 basename | grep -Po '(?<=.)\..*$' | sort | uniq
.bak
.c
.file
.file.bak
.input
.input.bak
.log
.log.bak
.out
.out.bak
.test
.test.bak
.txt
.txt.bak
一种非常简单的方法是对输出进行排序,只保留唯一的扩展,例如
find . -type f -regex ".*[.][a-zA-Z0-9][a-zA-Z0-9]*$" | \
awk -F '.' '{ print $NF }' | sort -u
如果您的排序
不支持-u
选项,则可以将排序
的结果传送到uniq
,例如
find . -type f -regex ".*[.][a-zA-Z0-9][a-zA-Z0-9]*$" | \
awk -F '.' '{ print $NF }' | sort | uniq
-regex
选项将find
选择限制为至少具有一个ASCII字符扩展名的文件名。但是,如果文件包含”,它也会拾取没有扩展名的文件。
,例如foo.bar.fatcat
将导致列表中包含fatcat
您可以调整正则表达式以满足需要。如果您的find
版本支持posix扩展正则表达式,那么您可以防止拾取更长的扩展。例如,要将扩展名限制为1-3
个字符,可以使用:
find . -type f -regextype posix-extended -regex ".*[.][a-zA-Z0-9]{1,3}$" | \
awk -F '.' '{ print $NF }' | sort -u
有其他方法可以实现这一点,但鉴于您最初的示例,这是一个很好的后续操作。一个非常简单的方法是对输出进行排序,只保留唯一的扩展,例如
find . -type f -regex ".*[.][a-zA-Z0-9][a-zA-Z0-9]*$" | \
awk -F '.' '{ print $NF }' | sort -u
如果您的排序
不支持-u
选项,则可以将排序
的结果传送到uniq
,例如
find . -type f -regex ".*[.][a-zA-Z0-9][a-zA-Z0-9]*$" | \
awk -F '.' '{ print $NF }' | sort | uniq
-regex
选项将find
选择限制为至少具有一个ASCII字符扩展名的文件名。但是,如果文件包含”,它也会拾取没有扩展名的文件。
,例如foo.bar.fatcat
将导致列表中包含fatcat
您可以调整正则表达式以满足需要。如果您的find
版本支持posix扩展正则表达式,那么您可以防止拾取更长的扩展。例如,要将扩展名限制为1-3
个字符,可以使用:
find . -type f -regextype posix-extended -regex ".*[.][a-zA-Z0-9]{1,3}$" | \
awk -F '.' '{ print $NF }' | sort -u
有其他方法可以实现这一点,但鉴于您最初的示例,这是一个密切的后续问题。要回答您的问题,awk行正在做什么: 正如您已经指出的,行
find-键入f
返回位于当前目录中的文件列表。例如
./foo.ext1
./bar.ext2
./spam.ext2
./ham.ext3
./spam.ham.eggs
此文件列表通过管道发送到命令awk-F!一个[$NF]+{print$NF}'
。此awk行包含大量信息。首先,您需要知道awk是一个记录解析器,其中每个记录都由多个字段组成。默认记录为行
,而默认字段分隔符为空格序列。那么,您的awk生产线现在做了什么:
::这将字段分隔符重新定义为点(-F.
)。从这一点开始,示例中的所有行现在都有2个字段(例如第1行
和foo
),而最后一行有3个字段(ext1
、spam
和ham
)eggs
::这是一个NF
变量,返回每个记录的字段数。很明显,扩展名由最后一个字段(awk
)表示$NF
:这是一个数组,其中索引是扩展名。默认数组值为a[$NF]
,除非您为其赋值零
::返回a[$NF]+
的当前值,并在返回后用1递增该值。因此,对于第1行,a[$NF]
返回a[“ext1”]++
,并将0
设置为a[“ext1”]
。而对于第3行,1
返回a[“ext2”]++
,并将1
设置为a[“ext2”]
。这表示2
跟踪出现a[$NF]
的次数$NF
:这结合了上述逻辑,但检查!a[$NF]+
的返回值是否为a[$NF]+
。如果是0
,则返回0
,否则返回true
。对于示例的第false
,此语句将返回2行
,因为true
具有值a[“ext2”]+
。但是,在语句0
的值为1。读取第3行时,语句将返回之后,[“ext2”]
。换句话说,我们已经看到false
了吗?当你用“是”或“否”回答这个问题时,用一增加$NF
的计数$NF
::这个组合了一切。它本质上表示,如果!一个[$NF]+{print$NF}
返回![$NF]+
,然后true
,但在打印之前,增量打印$NF
。或者换句话说,如果表示扩展名的字段(a[$NF]
)第一次出现,请打印该字段。如果它以前已经出现过,$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\u filename\u
)或其完整路径的一部分,打印时就好像它是扩展名一样。然而,结果是没有意义的,即/path/to/.secret/filename\u
最好通过以下方式解决此问题:/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}'