目录复制

今天与同学聊天时,听说了一个有趣的需求:复制指定目录中的所有目录文件到另一个指定的目录中.由于只复制目录,并不能用cp,mkdir等命令来解决,看来只能乖乖地写一个程序了..

c版

c语言写目录拷贝程序好复杂…不过效率确实很高,在其它语言中可能需要用系统调用执行mkdir,ls -l命令,而c语言则全都使用Linux本身的api接口…

这里主要使用了nftw函数,mkdir函数,chown函数.其中nftw函数是高级函数,用于遍历整个目录树,并提供一个回调函数用于处理目录树中的每个文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//get nftw() and S_IFSOCK declarations
#define _XOPEN_SOURCE 600
#include <stdio.h>
#include <ftw.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

//declaration of dstpath
static char *DSTPATH="test";

//try to cut the left '/' of path
static char *trim(char *path){
while(*path!='\0'){
if(*path=='/'){
path++;
return path;
}
path++;
}

return path;
}

//copy the src Dir to dst, and remain the authority and property
static int cpDir(const char *src, const char *dst,mode_t dstmode,uid_t uid,gid_t gid)
{
char path[255]="";
strcat(path,dst);
strcat(path,"/");
strcat(path,trim(src));
printf("making dir: %s\n",path);

if(access(path,F_OK)==0){
printf("the dir exists, skipping...");
return 0;
}
if(mkdir(path,dstmode)==-1){
perror("mkdir");
return -1;
}
chown(path,uid,gid);
return 0;
}

//function called by nftw()
static int dirTree(const char *pathname, const struct stat *sbuf, int type,
struct FTW *ftwb)
{
//return if path is not a directory
if (type != FTW_D)
return 0;
if(cpDir(pathname,DSTPATH,sbuf->st_mode,sbuf->st_uid,sbuf->st_gid)==-1)return -1;
return 0;
}

int main(int argc, char *argv[])
{
//usage: program src dst
if (argc != 3)
{
fprintf(stderr, "you need 2 arg!\n");
return -1;
}
DSTPATH=argv[2];
//nftw():travel the directory tree
if (nftw(argv[1], dirTree, 10, 0) == -1)
{
perror("nftw");
return -1;
}
return 0;
}

值得注意的是符号链接,这种情况下nftw()函数默认是解引用符号链接,即把符号链接当成一个目录来看待.如果有其他需求的话,可以添加FTW_PHYS标志位用于进一步错误

shell版

感觉到了shell的强大???比c不知道简单到哪边去了…学习c的动力-1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/bash

SRC=$1
DST=$2
TMPFILE=$(mktemp)

tree -dlinfug $SRC > $TMPFILE

while read line
do
array=($line)
srcfile=${array[3]}

if [[ ! $srcfile =~ $SRC ]];then
continue
fi

dstfile="$DST/${srcfile#*/}"

echo "making dir: $dstfile"

mkdir -p $dstfile
chmod --reference=$srcfile $dstfile
chown --reference=$srcfile $dstfile

done < $TMPFILE

rm -rf $TMPFILE

小结

这算是一个小的题目吧…中间查了好多资料,我确实感觉到了自身能力的不足

明日学习目标:docker-compose

0%