如何从path中提取文件名

在Linux API / POSIX中应该有一些优雅的东西来从完整path中提取基本文件名。 谢谢。

Solutions Collecting From Web of "如何从path中提取文件名"

请参阅char *basename(char *path)

或者在目标UNIX / POSIX系统上运行“ man 3 basename ”命令。

使用basename (具有奇怪的角落大小写的语义),或者通过调用strrchr(pathname, '/')并且将整个字符串作为基本名称(如果它不包含'/'字符)来完成。

下面是一个例子(给出char * whoami ),它说明了基本的算法:

 (whoami = strrchr(argv[0], '/')) ? ++whoami : (whoami = argv[0]); 

如果NULL是可能的,则需要额外的检查。 还要注意,这只是指向原始字符串 – “ strdup() ”可能是适当的。

如果您对目录名称感兴趣,也可以使用strstr

 char *path ="ab/cde/fg.out"; char *ssc; int l = 0; ssc = strstr(path, "/"); do{ l = strlen(ssc) + 1; path = &path[strlen(path)-l+2]; ssc = strstr(path, "/"); }while(ssc); printf("%s\n", path); 

当然,如果这是一个Gnu / Linux的问题,那么你可以使用库函数。

https://linux.die.net/man/3/basename

虽然有些人可能会不赞成这些符合POSIX标准的Gnu库函数,但不要使用const。 由于库函数功能很少做。 如果这对你很重要,我想你将不得不坚持自己的功能,或者以下将更符合你的口味?

 #include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { char *fn; char *input; if (argc > 1) input = argv[1]; else input = argv[0]; /* handle trailing '/' eg input == "/home/me/myprogram/" */ if (input[(strlen(input) - 1)] == '/') input[(strlen(input) - 1)] = '\0'; (fn = strrchr(input, '/')) ? ++fn : (fn = input); printf("%s\n", fn); return 0; } 

我不想在这里挑选其他人的帖子,但…

  1. 调用一些建议的“自制”功能(如: getFileNameFromPath("") )会使程序崩溃。
  2. 当命名函数固有地声称结果将是一个文件时,我会建议一些谨慎。 getFilenameFromPath("/usr/local")将返回"local" (不带引号),尽管在unix文件系统中,通常情况下它是一个文件夹。

我的例子:

 const char* getFileNameFromPath(const char* path) { for(size_t i = strlen(path) - 1; i >= 0; i--) { if (path[i] == '/') { return &path[i+1]; } } return path; } 

@Nikolay Khilyuk除了提供最好的解决方案。

1)回到使用char *,使用const绝对没有什么好的理由。

2)这个代码是不可移植的,并且很可能在没有/不是文件系统定界符的POSIX系统上失败,这取决于编译器的实现。 对于某些Windows编译器,您可能需要测试'\'而不是'/'。 您甚至可以测试系统并根据结果设置分隔符。

函数名称很长,但描述性,没有问题。 没有办法确定一个函数将返回一个文件名,只有当函数编码正确时,才能确定它是否成功。 虽然如果有人使用它不是一个路径的字符串显然会失败。 我可能会把它命名为basename,因为它会传达给许多程序员它的目的是什么。 这只是我的偏好,虽然基于我的偏见你的名字是好的。 至于字符串的长度,这个函数将会处理,为什么有人认为这将是一个点? 你将不太可能处理的路径名称比在ANSI C编译器上可以处理的时间长。 由于size_t被定义为一个unsigned long int,其范围为0到4,294,967,295。

我用下面的证明你的功能。

  #include <stdio.h> #include <string.h> char* getFileNameFromPath(char* path); int main(int argc, char *argv[]) { char *fn; fn = getFileNameFromPath(argv[0]); printf("%s\n", fn); return 0; } char* getFileNameFromPath(char* path) { for(size_t i = strlen(path) - 1; i; i--) { if (path[i] == '/') { return &path[i+1]; } } return path; } 

虽然丹尼尔·卡米尔·库扎(Daniel Kamil Kozar)找到了一个我曾经纠正过的错误, 该错误只会显示格式错误的绝对路径,但仍然该函数应该能够处理伪造的输入。 不要听每个批评你的人。 有些人只是喜欢有意见,即使不值钱。

我不喜欢strstr()解决方案,因为如果文件名与路径中的目录名称相同,并且是的,那么可能会发生,特别是在可执行文件通常没有扩展名的POSIX系统上,第一次,这将意味着你必须做多个测试,并用strstr()搜索分隔符更加麻烦,因为没有办法知道可能有多少个分隔符。 如果你想知道为什么一个人会想要一个可执行文件的基名认为busybox,egrep,fgrep等…

strrchar()实现起来很麻烦,因为它搜索字符而不是字符串,所以我没有发现它像这个解决方案一样可行或简洁。 由Rad Lexus纠正,这不会像我想的那样麻烦,因为strrchar()具有将字符串的索引返回到发现的字符之外的副作用。

保重