假设源代码文件名为test.cpp
。编译时,它会生成test.exe
个文件。当我执行它时,它应该识别它的文件名test.exe
并打印它。
我可以使用以下代码获取当前目录中存在的所有文件和目录的列表:
DIR * directory;
struct dirent * direct;
direct = readdir(directory);
但是,如何识别关联的文件名,在这种情况下是"test.exe"
?
答案 0 :(得分:16)
在主函数中,argv[0]
是命令行中可执行文件的名称
#include <stdio.h>
int main(int argc, char ** argv)
{
printf("%s", argv[0]);
return 0;
}
这将打印命令名称,该名称是相对于当前工作目录的目录,加上可执行文件名称(如果可用,则无法保证)
要获取当前工作目录,请使用getcwd()
标准库C函数。
从argv[0]
中的命令路径中提取文件名是特定于平台的:unix使用斜杠“/
”,windows允许混合使用斜杠/
和反斜杠\
,以及任何其他平台可以使用任何其他路径分隔符。从路径中提取文件名需要跨平台库,例如 Qt或Boost 。在 POSIX环境上,可以使用basename。
答案 1 :(得分:11)
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("%s\n", argv[0]);
return 0;
}
请注意,您的程序可以按以下方式启动:
/home/user/./app
在这种情况下,您可以使用strrchr
:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *appname;
appname = strrchr(argv[0], '/'); /* '\\' on Windows */
printf("%s\n", appname ? ++appname : argv[0]);
return 0;
}
答案 2 :(得分:6)
您在构建可执行文件时知道它的名称;该
最简单的解决方案是使用-D
或/D
将其嵌入到程序中
用于在命令行上定义宏的选项。
除此之外,通用答案是不可能的:
根据标准
argv[0]
应包含用于调用的名称 程序(无论那意味着什么)。哪个好,但1)它不是偶数 可以在Unix下实现,2)在大多数系统下,有各种各样的 别名,表示用于调用程序的名称 与可执行文件的名称无关。在Windows下
- 可以使用系统函数
GetModuleFileName
获取可执行文件的路径。一旦你有了路径,最后一个 path的元素是可执行文件的名称。在Unix下
- 这根本不可能。在启动新进程时,Unix 为可执行文件的路径和为什么获取单独的参数 最终在
argv[0]
,所以他们可能没有任何关系 另一个。这一切都取决于谁开始你的过程。bash
会 将完整路径放到环境变量"_"
中的可执行文件中, 所以你可以使用getenv
来获取它。但这只适用于您的计划 由bash
开始。在大多数Unices上,您也可以在中找到它/proc
文件系统,如果你知道你的方式;但是 这种情况的组织因Unix而异。还要注意 因为硬链接,你可执行的可能不只有一个 名称
真正的问题是你想要这样做的原因。你有什么问题 正试图解决?
答案 3 :(得分:3)
在Linux系统中,我认为您也可以使用basename(char *path);
中的libgen.h
,
试试$ man basename
:
打印NAME,删除任何前导目录组件。如果指定,也删除尾随的SUFFIX。
我试过它:
// filename.c
#include<stdio.h>
#include<stdlib.h>
#include<libgen.h>
int main(int argc, char* argv[]){
char* exe_name = basename(argv[0]);
printf(" Executable Name: %s", exe_name);
printf("\n");
return EXIT_SUCCESS;
}
观察,编译和测试为:
taxspanner@:~$ ls filename.c
filename.c
taxspanner@:~$ gcc -std=gnu99 -Wall -pedantic filename.c -o filename
taxspanner@:~$ ls filename*
filename filename.c
taxspanner@:~$
现在在当前目录中运行它:
taxspanner@:~$ ./filename
Executable Name: filename
使用绝对路径:
taxspanner@:~$ pwd
/home/taxspanner
taxspanner@:~$ /home/taxspanner/filename
Executable Name: filename
相对路径:
taxspanner@:~$ cd study/divide-5/
taxspanner@:~/study/divide-5$ pwd
/home/taxspanner/study/divide-5
taxspanner@:~/study/divide-5$ ls ../../filename*
../../filename ../../filename.c
taxspanner@:~/study/divide-5$ ../../filename
Executable Name: filename
taxspanner@:~/study/divide-5$
再试一次带有后缀的可执行文件名:
taxspanner@:~$ gcc -std=gnu99 -Wall -pedantic filename.c -o filename.out
taxspanner@:~$ ./filename.out
Executable Name: filename.out
taxspanner@:~$ cd study/divide-5/
taxspanner@:~/study/divide-5$ ../../filename.out
Executable Name: filename.out
Be careful when using it:dirname()
和basename()
都可以修改路径的内容,因此在调用其中一个函数时,可能需要传递副本
试一试!!
答案 4 :(得分:3)
您可以使用proc(5)和/proc/self/exe
符号链接,因此请使用readlink(2)。完成后,您可以在获得的符号链接上使用basename(3)或realpath(3)。
但是,请注意,程序可能并不总是具有文件路径。它可以有几个文件路径(例如/bin/rbash
是/bin/bash
的符号链接,并且当调用rbash
或{{1}时,shell进程的行为会有所不同}})。有时,给定文件(实际上是inode,请参阅inode(7))有几个硬链接。在奇怪的情况下,没有。
并且可能会发生一个程序execve(2) - 然后使用unlink(2)删除(可能来自计划在您之前运行的另一个进程)等。
(顺便说一句,您的问题是特定于操作系统的; readdir(3)是POSIX,有些操作系统甚至没有目录,C11标准没有提及bash
;阅读n1570)
我尝试了以下(病态)readdir
程序(在我的./selfremove
目录中),删除了自己的二进制文件:
/home/basile/tmp/
它有效,并且内核正在构造一个 // file selfremove.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int
main (int argc, char **argv)
{
char selfpath[128];
memset (selfpath, 0, sizeof (selfpath));
if (readlink ("/proc/self/exe", selfpath, sizeof (selfpath) - 1) < 0)
{
perror ("first readlink");
exit (EXIT_FAILURE);
};
printf ("initial /proc/self/exe -> %s\n", selfpath);
if (unlink (argv[0]))
{
fprintf (stderr, "unlink %s: %m\n", argv[0]);
exit (EXIT_FAILURE);
};
printf ("%s unlinked\n", argv[0]);
if (readlink ("/proc/self/exe", selfpath, sizeof (selfpath) - 1) < 0)
{
perror ("second readlink");
exit (EXIT_FAILURE);
};
printf ("final /proc/self/exe -> %s\n", selfpath);
return 0;
}
符号链接(因为反向编码器可能会将可执行文件重命名为* (deleted)
,因此内核添加后缀只是一个指示......):< / p>
selfremove (deleted)
所以即使使用 % ./selfremove
initial /proc/self/exe -> /home/basile/tmp/selfremove
./selfremove unlinked
final /proc/self/exe -> /home/basile/tmp/selfremove (deleted)
,您也无法始终信任结果。
如果您认为您的程序已由execve(2) - 由某个shell(或执行execvp(3)的类似程序) - 而且总是的情况 - 而是PATH
variable可能已被使用(如果没有/proc/self/exe
,则会从main
argv[0]
中搜索/
。您可以使用getenv(3)作为getenv("PATH")
从您的环境中获取它(有关详情,请参阅environ(7))。通常会设置和使用$PATH
,但它们也是病态案例。
所以一般来说,没有办法可靠地打印自己的可执行文件(正如我的病态selfremove.c
所示)。在大多数情况下,您可以找到它(例如readlink
的{{1}},或使用/proc/self/exe
在$PATH
中搜索。