find . -iname "*.sh" | sed 's/[.]sh$//'
./backup/samukano/ex04/who_am_i
./backup/samukano/ex05/people
./days/day01/samukano/ex01/print_groups
./days/day01/samukano/ex02/find_sh
./samukano/ex04/who_am_i
./samukano/ex05/people
我只需要
who_am_i
people
...
people
答案1
find . -iname "*.sh" -exec basename {} \; | sed s/\.sh//g
该basename
实用程序将从路径中删除所有目录信息(相对或绝对)。
如果需要的话,实用dirname
程序会执行相反的操作。
答案2
总结
便携,但不坚固:
find . -type f \( -name "*.sh" -o -name "*.Sh" -o -name "*.sH" -o -name "*.SH" \) |
sed -e 's|^.*/||' -e 's/[.][sS][hH]$//'
健壮,用于解析为以空字符结尾的字符串:
find . -type f -iname "*.sh" -printf "%f\0" | sed -z 's/[.][sS][hH]$//'
内部强大,可能有模棱两可的输出,供查看:
find . -type f -iname "*.sh" -printf "%f\0" | sed -z 's/[.][sS][hH]$/\n/'
完整答案
有很多方法,有些方法比其他方法更强大。此外,您可能想要使用的工具具有重叠的功能,但其中许多工具都不是 POSIX,因此您可能有或没有所需的选项。
此外,任何文件名的目录都可能包含换行符和其他奇怪字符。因此,为了以稳健的方式解析文件名,您需要将它们视为以空字符结尾的字符串。
然后,您可能还是希望将结果打印为以换行符结尾的(即常规)字符串,以便于人类阅读(但可能会产生歧义的输出)。
工具通常支持具有非 POSIX 扩展的空终止字符串。
例如,为了摆脱这些主要问题的完整路径,您可以使用:
find . -printf "%f"
,但你find
可能会支持也可能不支持-printf
;- 或者
basename
; - 甚至
sed
。
要剥离,.sh
您可以使用:
basename path_to_process .sh
,但它区分大小写,我猜你使用它-iname
是有原因的(注意-iname
这不是 POSIX 所要求的);- 或者
sed
(像你做的那样),可以不区分大小写。
这个分析并不详尽。
最强大的、不区分大小写的版本返回以空字符结尾的字符串。这使得输出对于进一步的解析完全可靠:
find . -type f -iname "*.sh" -printf "%f\0" | sed -z 's/[.][sS][hH]$//'
相同,返回人类可读的且可能有歧义的输出:
find . -type f -iname "*.sh" -printf "%f\0" | sed -z 's/[.][sS][hH]$/\n/'
歧义表现如下:
foo
bar
是否有两个脚本:foo.sh
和bar.sh
?还是只有一个foo(newline here)bar.sh
?
如果您不能使用而必须以换行符结尾的字符串sed -z
提供输入,情况会变得更加混乱。在这种情况下,单个文件也会生成上述输出。sed
foo.sh(newline here)bar.sh
如果您sed
支持-z
但find
不支持怎么办-printf
?也许您的basename
支持-z
。这应该是完全健全的:
find . -type f -iname "*.sh" -exec basename -z -a {} + | sed -z 's/[.][sS][hH]$//'
或者不支持-a
:
find . -type f -iname "*.sh" -exec basename -z {} \; | sed -z 's/[.][sS][hH]$//'
我看得出您find
确实支持-iname
,但也可能不支持。如果没有呢?相当幼稚但有效的方法:
find . -type f \( -name "*.sh" -o -name "*.Sh" -o -name "*.sH" -o -name "*.SH" \) ...
正如您所见,这一切都取决于可用的选项。
最后假设你的路径使用安全设置可打印字符(无换行符等)。此命令应便携的并且足够好:
find . -type f \( -name "*.sh" -o -name "*.Sh" -o -name "*.sH" -o -name "*.SH" \) |
sed -e 's|^.*/||' -e 's/[.][sS][hH]$//'