수색…
디렉토리에있는 텍스트 파일 수를 센다.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
#include <ctype.h>
int main(int argc, char **argv)
{
const char *dname = (argc > 1 ? argv[1] : ".");
DIR* pdir = opendir(dname);
if(pdir == NULL) {
perror("Can't open directory");
return EXIT_FAILURE;
}
int textfiles=0;
struct dirent* dent;
while ((dent=readdir(pdir))!=NULL) {
int d_name_len = strlen(dent->d_name);
if (d_name_len > 4 &&
strcmp(dent->d_name + (d_name_len - 4), ".txt") == 0) {
textfiles++;
}
}
printf("Number of text files: %i\n", textfiles);
closedir(pdir);
return 0;
}
재귀 적으로 파일을 제거합니다 (nftw, thread-safe가 아닙니다).
#define _XOPEN_SOURCE 500
#include <stdlib.h> /* for exit() */
#include <stdio.h> /* for remove() */
#include <ftw.h> /* for nftw() */
int unlink_cb(
const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
{
return remove(fpath);
}
int rm_rf(const char *path)
{
return nftw(path,
unlink_cb,
64 /* number of simultaneously opened fds, up to OPEN_MAX */,
FTW_DEPTH | FTW_PHYS);
}
FTW_PHYS
플래그는 심볼릭 링크를 따르지 않음을 의미합니다.
FTW_DEPTH
플래그는 post-order traversal을 수행합니다. 즉, 디렉토리와 하위 디렉토리의 내용을 처리 한 후 디렉토리 자체에 대해 unlink_cb()
를 호출합니다.
콜백 함수가 0이 아닌 값을 반환하면 nftw
가 중단됩니다.
참고 :이 메서드는 스레드로부터 안전하지 않습니다. nftw
가 chdir
사용하기 때문입니다.
재귀 적으로 파일을 제거합니다 (openat 및 unlinkat, thread-safe).
#include <stddef.h> /* for offsetof() */
#include <stdlib.h> /* for exit() */
#include <stdio.h> /* for perror() */
#include <string.h> /* for strcmp() */
#include <unistd.h> /* for close(), unlink() */
#include <fcntl.h> /* for open() */
#include <dirent.h> /* for DIR */
#include <sys/stat.h> /* for stat */
#include <limits.h> /* for NAME_MAX */
int rm_rf(const char* path)
{
if (unlink(path) == 0) {
return 0;
} else {
int dirfd = open(path, O_RDONLY | O_DIRECTORY);
if (dirfd == -1) {
perror("open");
return -1;
}
if (rm_children(dirfd) == -1) {
return -1;
}
if (rmdir(path) == -1) {
perror("rmdir");
return -1;
}
return 0;
}
}
int rm_children(int dirfd)
{
DIR* dir = fdopendir(dirfd);
if (dir == NULL) {
perror("fdopendir");
if (close(dirfd) == -1) {
perror("close");
}
return -1;
}
char buf[offsetof(struct dirent, d_name) + NAME_MAX + 1];
struct dirent* dbuf = (struct dirent*)buf;
struct dirent* dent = NULL;
int ret = 0;
for (;;) {
if ((ret = readdir_r(dir, dbuf, &dent)) == -1) {
perror("readdir_r");
break;
}
if (dent == NULL) {
break;
}
if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) {
continue;
}
if ((ret = rm_at(dirfd, dent->d_name)) == -1) {
break;
}
}
if (closedir(dir) == -1) {
perror("closedir");
ret = -1;
}
return ret;
}
int rm_at(int dirfd, const char* name)
{
int fd = openat(dirfd, name, O_RDONLY);
if (fd == -1) {
perror("openat");
return -1;
}
int ret = 0;
struct stat st;
if ((ret = fstat(fd, &st)) == -1) {
perror("fstat");
goto out;
}
if (S_ISDIR(st.st_mode)) {
ret = rm_children(fd);
fd = -1;
if (ret == -1) {
goto out;
}
}
ret = unlinkat(dirfd, name, S_ISDIR(st.st_mode) ? AT_REMOVEDIR : 0);
if (ret == -1) {
perror("unlinkat");
goto out;
}
out:
if (fd != -1) {
if (close(fd) == -1) {
perror("close");
ret = -1;
}
}
return ret;
}
주 :이 메서드는 thread에 대해서 안전 합니다만, 제어되지 않는 재귀를 위해서 (때문에) stack를 사용합니다. 각 트리 레벨은 적어도 NAME_MAX 바이트 + 하나의 프레임 크기를 추가합니다.
Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow