C程序,打印其可执行文件名

时间:2014-11-26 12:41:09

标签: c++ c

假设源代码文件名为test.cpp。编译时,它会生成test.exe个文件。当我执行它时,它应该识别它的文件名test.exe并打印它。

我可以使用以下代码获取当前目录中存在的所有文件和目录的列表:

DIR * directory;
struct dirent * direct;
direct = readdir(directory);

但是,如何识别关联的文件名,在这种情况下是"test.exe"

5 个答案:

答案 0 :(得分:16)

在主函数中,argv[0]是命令行中可执行文件的名称

#include <stdio.h>
int main(int argc, char ** argv)
{
    printf("%s", argv[0]);
    return 0;
}

Live Demo

这将打印命令名称,该名称是相对于当前工作目录的目录,加上可执行文件名称(如果可用,则无法保证) 要获取当前工作目录,请使用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 itdirname()basename()都可以修改路径的内容,因此在调用其中一个函数时,可能需要传递副本

试一试!!

答案 4 :(得分:3)

特别是在Linux上:

您可以使用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中搜索。