如果我有一个脚本,无论出于何种原因,需要将当前工作目录作为其存储的目录,我可以运行cd "$(dirname "${0}")"
。使用C程序有一些简单的方法吗?
答案 0 :(得分:2)
答案 1 :(得分:2)
$0
对应于C程序中的argv[0]
。但是,如果基于PATH
找到该命令,则该方法将不起作用。
在Linux中,您可以检查/proc/self/exe
伪符号链接以查看当前进程正在执行的二进制文件。您可以使用readlink("/proc/self/exe", buffer, size)
获取当前可执行文件的路径。
例如,您可以使用例如
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
/* Return the path to the directory the current executable
resides in, as a dynamically allocated string.
If an error occurs, returns NULL with errno set.
*/
char *exe_dir(void)
{
size_t size = 512, i, n;
char *path, *temp;
while (1) {
ssize_t used;
path = malloc(size);
if (!path) {
errno = ENOMEM;
return NULL;
}
used = readlink("/proc/self/exe", path, size);
if (used == -1) {
const int saved_errno = errno;
free(path);
errno = saved_errno;
return NULL;
} else
if (used < 1) {
free(path);
errno = EIO;
return NULL;
}
if ((size_t)used >= size) {
free(path);
size = (size | 2047) + 2049;
continue;
}
size = (size_t)used;
break;
}
/* Find final slash. */
n = 0;
for (i = 0; i < size; i++)
if (path[i] == '/')
n = i;
/* Optimize allocated size,
ensuring there is room for
a final slash and a
string-terminating '\0', */
temp = path;
path = realloc(temp, n + 2);
if (!path) {
free(temp);
errno = ENOMEM;
return NULL;
}
/* and properly trim and terminate the path string. */
path[n+0] = '/';
path[n+1] = '\0';
return path;
}
请注意,您不一定需要使用chdir()
来更改该路径;您也可以使用例如打开它open(path, O_PATH)
并将该文件描述符用作openat()
和其他* at()函数的参数。
如果文件系统层次结构中的可执行文件非常深,则由于此伪符号链接的性质,这可能会返回带errno == ENAMETOOLONG
的NULL。替代方法,比如从/proc/self/maps
或/proc/self/smaps
读取路径,会遇到一个未修复的内核错误(我已经报告过),其中带有反斜杠\
的路径被错误地转义。
在任何情况下,如果exe_dir()
返回NULL,我热烈建议您的程序只是向用户报告无法确定当前可执行文件所在的目录(可能与原因strerror(errno)
一起)和中止。
答案 2 :(得分:1)