test.cpp
。编译后,它将生成test.exe
文件。执行时,它应该能够识别自己的文件名test.exe
并打印输出。以下代码可以获取当前目录中所有文件和目录的列表:
DIR * directory;
struct dirent * direct;
direct = readdir(directory);
但是,在这种情况下,我该如何识别关联的文件名,即 "test.exe"
?
test.cpp
。编译后,它将生成test.exe
文件。执行时,它应该能够识别自己的文件名test.exe
并打印输出。DIR * directory;
struct dirent * direct;
direct = readdir(directory);
但是,在这种情况下,我该如何识别关联的文件名,即 "test.exe"
?
在你的主函数中,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。
argv[0]
可以是任何东西。Shell 将用户输入的命令作为 argv[0]
传递。它可能与文件名有关,也可能与文件名无关,这取决于 Shell。通常情况下,运行其他程序的程序可以自由地将任何内容作为 argv
传递。 - n. m.#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;
}
basename
吗? - Jonatan Goebel-D
或/D
选项在命令行上定义一个宏即可。argv[0]
应包含用于调用程序的名称(无论这意味着什么)。 这很好,但1)在Unix下甚至无法实现,2)在大多数系统下,有各种别名使得用于调用程序的名称与可执行文件的名称毫无关系。GetModuleFileName
,可以用来获取可执行文件的路径。 一旦您拥有了路径,路径的最后一个元素就是您的可执行文件的名称。argv [0]
中的参数分别提供独立的参数,因此它们潜在地互不相关。 这完全取决于谁启动了您的进程。 bash
将可执行文件的完整路径放在环境变量"_"
中,因此您可以使用getenv
来获取它。但这仅适用于您的程序是由bash
启动的情况。 在大多数Unix系统上,还可以在/proc
文件系统中找到它,如果您知道路径的话; 但这种组织方式各不相同。 请注意,由于硬链接,可执行文件可能没有一个名称。您可能会使用proc(5)和/proc/self/exe
符号链接,因此请使用readlink(2)。完成后,您可以对所获得的符号链接使用basename(3)或realpath(3)。
然而,请注意程序可能并不总是有一个文件路径。它可能有 多个 文件路径(例如,/bin/rbash
是指向 /bin/bash
的符号链接,当作为 rbash
或 bash
调用时,Shell 进程的行为不同)。有时一个给定的文件(实际上是 inode,请参见inode(7))有 多个 硬链接。在奇怪的情况下可能没有硬链接。同时,在程序被 execve(2) 启动后,可能会使用 unlink(2) 移除该程序 (也许是由于其他进程计划在你的进程之前运行等原因)。
readdir
;通过阅读n1570来进行检查)./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;
}
它可以工作,内核正在构建一个 * (已删除)
符号链接(因为一些恶意程序员可能会将可执行文件重命名为 selfremove (已删除)
,所以内核添加的后缀只是一个指示……):
% ./selfremove
initial /proc/self/exe -> /home/basile/tmp/selfremove
./selfremove unlinked
final /proc/self/exe -> /home/basile/tmp/selfremove (deleted)
/proc/self/exe
,您也不能始终信任结果。PATH
变量 有可能被使用(如果它没有 /
,那么会从主函数的 argv[0]
中搜索)。你可以使用 getenv(3) 函数来获取它,例如 getenv("PATH")
,从你的环境中获取(请参见 environ(7) 获取更多信息)。通常会设置和使用该变量,但也有一些特殊情况。
通常情况下,没有可靠的方法打印自己的可执行文件(正如我的病态selfremove.c
所示)。在大多数情况下,您可以找到它(例如通过/proc/self/exe
的readlink
或使用argv [0]
在$PATH
中搜索)。
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
使用时要小心:无论是dirname()
还是basename()
都可能修改路径的内容,因此在调用这些函数时最好传递一个副本。
试一试吧!!
program*
来启动相对路径下的程序。 - David Ranieri*
,我只是使用了 ../../filename
。 - Grijesh Chauhan