1.列出目录中的所有文件
/* Listing 18-2 */
/* list_files.c*/
#if defined(__APPLE__)
/* Darwin requires this header before including <dirent.h> */
#include <sys/types.h>
#endif
#include <dirent.h>
#include "tlpi_hdr.h"
static void /* 列出目录'dirpath'的所有文件 */
listFiles(const char *dirpath) {
DIR *dirp;
struct dirent *dp;
Boolean isCurrent; /* 判断dirpath是否是当前目录. */
isCurrent = strcmp(dirpath, ".") == 0;
/**打开指定目录,返回一个DIR指针*/
dirp = opendir(dirpath);
if (dirp == NULL) {
errMsg("opendir failed on '%s'", dirpath);
return;
}
/* 读取每个DIR条目,打印目录+文件名 */
for (;;) {
errno = 0; /* 打印readdir过程中错误 */
dp = readdir(dirp);
if (dp == NULL)
break;
/**如果d_name是.或..,继续循环*/
if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
continue;
/**如果是当前目录,则不打印dir部分*/
if (!isCurrent)
printf("%s/", dirpath);
printf("%s
", dp->d_name);
}
if (errno != 0)
errExit("readdir");
if (closedir(dirp) == -1)
errMsg("closedir");
}
int
main(int argc, char *argv[]) {
if (argc > 1 && strcmp(argv[1], "--help") == 0)
usageErr("%s [dir-path...]
", argv[0]);
if (argc == 1) /* 没有传参数,则默认是当前目录. */
listFiles(".");
else
for (argv++; *argv; argv++)
listFiles(*argv);
exit(EXIT_SUCCESS);
}
2.递归遍历目录
/* Listing 18-3 */
/* nftw_dir_tree.c
*/
#if defined(__sun)
#define _XOPEN_SOURCE 500 /* Solaris 8 needs it this way */
#else
#if ! defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600
#define _XOPEN_SOURCE 600 /* Get nftw() and S_IFSOCK declarations */
#endif
#endif
#include <ftw.h>
#include "tlpi_hdr.h"
static void
usageError(const char *progName, const char *msg)
{
if (msg != NULL)
fprintf(stderr, "%s
", msg);
fprintf(stderr, "Usage: %s [-d] [-m] [-p] [directory-path]
", progName);
fprintf(stderr, " -d Use FTW_DEPTH flag
");
fprintf(stderr, " -m Use FTW_MOUNT flag
");
fprintf(stderr, " -p Use FTW_PHYS flag
");
exit(EXIT_FAILURE);
}
static int /* 自定义函数,以备nftw()调用 */
dirTree(const char *pathname, const struct stat *sbuf, int type,struct FTW *ftwb)
{
if (type == FTW_NS) { /* 调用stat失败 */
printf("?");
} else {
switch (sbuf->st_mode & S_IFMT) { /* 打印文件类型 */
case S_IFREG: printf("-"); break;
case S_IFDIR: printf("d"); break;
case S_IFCHR: printf("c"); break;
case S_IFBLK: printf("b"); break;
case S_IFLNK: printf("l"); break;
case S_IFIFO: printf("p"); break;
case S_IFSOCK: printf("s"); break;
default: printf("?"); break; /* Should never happen (on Linux) */
}
}
printf(" %s ", (type == FTW_D) ? "D " : (type == FTW_DNR) ? "DNR" :
(type == FTW_DP) ? "DP " : (type == FTW_F) ? "F " :
(type == FTW_SL) ? "SL " : (type == FTW_SLN) ? "SLN" :
(type == FTW_NS) ? "NS " : " ");
if (type != FTW_NS)
printf("%7ld ", (long) sbuf->st_ino);
else
printf(" ");
printf(" %*s", 4 * ftwb->level, ""); /* 用缩进代表级别 */
printf("%s
", &pathname[ftwb->base]); /* 打印basename */
return 0; /* Tell nftw() to continue */
}
int main(int argc, char *argv[])
{
int flags, opt;
flags = 0;
while ((opt = getopt(argc, argv, "dmp")) != -1) {
switch (opt) {
case 'd': flags |= FTW_DEPTH; break;/*后序遍历*/
case 'm': flags |= FTW_MOUNT; break;/*不越界进入另一个文件系统*/
case 'p': flags |= FTW_PHYS; break;/*不对符号链接解引用*/
default: usageError(argv[0], NULL);
}
}
if (argc > optind + 1)
usageError(argv[0], NULL);
if (nftw((argc > optind) ? argv[optind] : ".", dirTree, 10, flags) == -1) {
perror("nftw");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
3.打印路径中的目录和文件名
/* Listing 18-5 */
/* t_dirbasename.c
*/
#include <libgen.h>
#include "tlpi_hdr.h"
/**打印路径的目录部分和文件名部分
* dirname()和 basename()均可修改pathname所指向的字符串。
* 因此,如果希望保留原有的路径名字符串,那么就必须向 dirname()和 basename()传递该字符串的副本
* 使用strdup()该函数调用了 malloc()来制作传递给dirname()和basename()的字符串副本,
* 然后再使用 free()将其释放
* */
int
main(int argc, char *argv[])
{
char *t1, *t2;
int j;
for (j = 1; j < argc; j++) {
t1 = strdup(argv[j]);
if (t1 == NULL)
errExit("strdup");
t2 = strdup(argv[j]);
if (t2 == NULL)
errExit("strdup");
printf("%s ==> %s + %s
", argv[j], dirname(t1), basename(t2));
free(t1);
free(t2);
}
exit(EXIT_SUCCESS);
}
4.unlink的应用
/* Listing 18-1 */
/** t_unlink.c
一个文件被unlink,当他还有被打开的文件描述符时他实际是没有被删的,
此时还能进行写入,close(fd)后文件才真正被删
Usage: t_unlink file
*/
#include <sys/stat.h>
#include <fcntl.h>
#include "tlpi_hdr.h"
#define CMD_SIZE 200
#define BUF_SIZE 1024
int
main(int argc, char *argv[])
{
int fd, j, numBlocks;
char shellCmd[CMD_SIZE]; /* 调用的shell命令 */
char buf[BUF_SIZE]; /* 随机写入一定字节 */
if (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s temp-file [num-1kB-blocks]
", argv[0]);
numBlocks = (argc > 2) ? getInt(argv[2], GN_GT_0, "num-1kB-blocks")
: 100000;
/* 创建一个新文件 */
fd = open(argv[1], O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
if (fd == -1)
errExit("open");
if (unlink(argv[1]) == -1) /* 删除文件 */
errExit("unlink");
for (j = 0; j < numBlocks; j++) /* 写入文件 */
if (write(fd, buf, BUF_SIZE) != BUF_SIZE)
fatal("partial/failed write");
/**将命令df写入shellCmd中,并执行shell命令*/
snprintf(shellCmd, CMD_SIZE, "df -k `dirname %s`", argv[1]);
system(shellCmd); /* 查看文件占用空间 */
if (close(fd) == -1) /* 关闭文件描述符,此时文件才被删除 */
errExit("close");
printf("********** Closed file descriptor
");
system(shellCmd); /* 重新查看占用空间 */
exit(EXIT_SUCCESS);
}
5.读取并解析一个符号链接
/* Listing 18-4 */
/* view_symlink.c
读取并解析一个符号链接
*/
#include <sys/stat.h>
#include <limits.h> /* For definition of PATH_MAX */
#include "tlpi_hdr.h"
#define BUF_SIZE PATH_MAX
int
main(int argc, char *argv[])
{
struct stat statbuf;
char buf[BUF_SIZE];
ssize_t numBytes;
if (argc != 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s pathname
", argv[0]);
/* 检查提供的路径名是否为一个符号链接 */
if (lstat(argv[1], &statbuf) == -1)
errExit("lstat");
if (!S_ISLNK(statbuf.st_mode))
fatal("%s is not a symbolic link", argv[1]);
numBytes = readlink(argv[1], buf, BUF_SIZE - 1);
if (numBytes == -1)
errExit("readlink");
buf[numBytes] = '