如何区分带后缀和不带后缀的文件名?

How can I distinguish between file names with and without suffix?

我正在写一个bash shell脚本来输出文件名的后缀。

在这种情况下我使用:

sed 's|.*\.||'

所以输出是例如:

png
exe
c

但是如果文件名没有后缀因此没有点怎么办?我的输出应该是 "no suffix",但我不知道如何使用 sed 执行此操作。

编辑 我已经尝试过的:

目录:

abc.x
abc.y
abc

输入:

find . -type f | sed -E 's/^[^.]+$/no suffix/; s/.*\.//'

输出:

x
y
/abc

使用 2 个连续替换:

sed -E 's/^[^.]+$/no suffix/; s/.+\.//'

awk 中的一个。首先是一些未提供的测试material:

$ cat foo
this.foo
that.bar
nothing

awk:

$ awk '{n=split([=11=],a,".");print (n>1?a[n]:"no suffix")}' foo
foo
bar
no suffix

怎么样

sed '/.*\./s///;t;s/.*/no suffix/'

正则表达式匹配带点的行。在这些行上,我们执行替换。如果发生替换,我们就完成了。否则,执行其他替换。

在替换模式中使用空正则表达式使用了先前的模式。如果发生替换,t 命令分支;没有参数,我们分支到脚本的末尾。 (否则,您可以使用 :label 设置标签并使用 tlabel 分支到该标签。)

$ cat file
abc.x
abc.y
abc

$ awk -F'.' '{print (NF>1 ? $NF : "no suffix")}' file
x
y
no suffix

您可以使用 POSIX shell 参数扩展 完成相同的操作,而无需调用单独的实用程序。例如,要测试文件是否包含 '.',您可以简单地使用 test,例如:

[ "$i" = "${i%.*}" ]

Posix Programmer's Manual - Shell Command Language - Parameter Expansion

如果它测试为 TRUE,则不存在扩展,否则,您可以使用额外的 参数扩展 来获取扩展本身,例如

[ "$i" = "${i%.*}" ] && echo "$i - no suffix" || echo "$i - ${i##*.}"

(注意: 您需要额外的测试来排除 .foo(例如 dotfiles),但剩下的给你)

将其包装在一个循环中并排除目录文件,您可以测试目录中的每个文件或在循环中使用 read 并将名称列表传递给它。例如,遍历目录中的文件将导致:

...
ftlcdfil.c - c
geany-plugin_build_w_gtk+2.patch - patch
geany-plugins.spec - spec
geany.spec - spec
geany_build_w_gtk+2.patch - patch
getfl - no suffix
gtkw_save_test.txt - txt
gtkwrite-master.zip - zip
helloleap - no suffix
helloleap.c - c
jnl - no suffix
messages - no suffix
opensuse_15.0_1s_delay.svg - svg
...

使用 Perl

/tmp> ls ab*
abc  abc.x  abc.y
/tmp> perl -e ' print /\./? "$_\n" : "no suffix\n" for(glob("ab*")) '
no suffix
abc.x
abc.y
/tmp>