【发布时间】:2021-06-03 21:39:15
【问题描述】:
我正在编写一个模仿 UNIX shell 的 c 编程,我想知道是否有办法在特定目录中找到可执行文件(命令文件)
【问题讨论】:
我正在编写一个模仿 UNIX shell 的 c 编程,我想知道是否有办法在特定目录中找到可执行文件(命令文件)
【问题讨论】:
通过可执行文件,我假设您正在查找不是设置了执行标志的目录的任何文件。
实现目标的一种方法是:
dirent结构体的d_name获得),将此路径传递给stat ,并使用 inode documentation 中指定的位掩码检查执行权限。代码:
#include <stdio.h>
#include <sys/types.h> //opendir, stat
#include <dirent.h> //opendir
#include <errno.h>
#include <string.h>
#include <sys/stat.h> //stat
#include <stdlib.h> //free, malloc
int main(int argc, char** argv) {
if (argc < 2) {
fprintf(stderr, "Usage: ./a.out path_to_a_directory \n");
return 1;
}
char* path_to_directory = argv[1];
int path_length = strlen(path_to_directory);
int modified = 0;
//Modify path so that a dash is at the end.
if (path_to_directory[path_length - 1] != '/') {
char* modified_path = (char *) malloc(sizeof(char) * (strlen(path_to_directory) + 2));
//Copies the null character as well.
strcpy(modified_path, path_to_directory);
modified_path[path_length] = '/';
modified_path[path_length + 1] = '\0';
path_to_directory = modified_path;
//Set flag to true so that the dynamically allocated memory is freed later.
modified = 1;
}
//Get the directory stream corresponding to the directory.
DIR* in_directory_stream = opendir(path_to_directory);
if (in_directory_stream == NULL) {
fprintf(stderr, "Error: the specified directory cannot be found or opened. \n", errno);
if (modified) free(path_to_directory);
return 1;
}
dirent* entry = NULL;
printf("Files that are executable by at least one of the permission classes (owner, group, others) are: \n");
while ((entry = readdir(in_directory_stream)) != NULL) {
//All directories contain . and .., which corresponds to current and parent directory respectively,
//in unix systems. Since we are looking for only executable files, we can ignore them.
if (!strcmp(".", entry->d_name)) {
continue;
}
if (!strcmp("..", entry->d_name)) {
continue;
}
//Get file information.
struct stat entry_info;
/* Create the absolute path of the entry.
* Without it, as mentioned by Shawn below,
* stat will look for a file with the entry's name in current working directory
* instead of the specified directory.
*/
char* entry_absolute_path = (char *) malloc(sizeof(char) * (strlen(path_to_directory)
+ strlen(entry->d_name) + 1));
strcat(entry_absolute_path, path_to_directory);
strcat(entry_absolute_path, entry->d_name);
if (stat(entry_absolute_path, &entry_info) == -1) {
fprintf(stderr, "Error in obtaining file information about %s\n", entry->d_name);
} else {
// Check if the file is not a directory and
// is executable by one of the permission classes (owner, group, others).
if (((entry_info.st_mode & S_IFMT) != S_IFDIR) &&
((entry_info.st_mode & S_IXUSR) || (entry_info.st_mode & S_IXGRP)
|| (entry_info.st_mode & S_IXOTH))) {
printf("%s\n", entry->d_name);
}
}
free(entry_absolute_path);
}
//Close directory stream.
closedir(in_directory_stream);
if (modified) free(path_to_directory);
return 0;
}
编辑:更正了程序以将文件的绝对路径传递给stat。在此编辑之前,stat 仅给出了文件名,导致程序仅搜索当前工作目录。 Shawn 识别的错误
【讨论】:
dirent 结构中的文件名不包含目录。 stat() 也需要这个。
dirent 结构中的文件名不包含目录”是什么意思?我的理解是,如果一个目录包含一个子目录,当我们遍历目录流时,我们会得到一个与该子目录对应的dirent struct。
opendir() "/foo/bar/",文件名前面没有/foo/bar/,所以除非你正在扫描你当前的工作目录,否则stat()会失败除非 cwd 中恰好存在同名的文件——在这种情况下,它会查看错误的文件。