简单实现cp命令
源和目的操作数都只能是文件名。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
//参数错误退出
int main(int argc, char* argv[]){
if(argc != 3){
perror("参数不对");
exit(0);
}
int fr = open(argv[1],O_RDONLY );
struct stat sbuf;
stat(argv[1], &sbuf);
//不存在就创建,存在就失败
int fw = open(argv[2], O_WRONLY|O_CREAT|O_EXCL, sbuf.st_mode);
if(-1 == fw){
printf("目标文件已经存在,是否覆盖?(y/n)");
char ch;
scanf("%c", &ch);
if(ch == 'y'){
fw = open(argv[2], O_WRONLY|O_TRUNC, sbuf.st_mode);
}
else{
exit(1);
}
}
int r = 0;
char buf[1024] = "";
while((r = read(fr, buf, 1024)) > 0){
write(fw, buf, r);
memset(buf, 0x00, 1024);
}
close(fw);
close(fr);
}
简易ls:取当前目录,排序后输出
用链表实现,每读取一个文件或目录插入到已排序链表。
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
typedef struct node_t{
char name[1024];
struct node_t *next;
}node_t;
int main(){
//打开一个目录流
DIR *pDir = opendir(".");
if(pDir == NULL)
perror("opendir");
node_t *pHead = NULL;
struct dirent *pd = NULL;
//从目录流读取一个目录结构体
while((pd = readdir(pDir)) != NULL){
node_t *pNew = (node_t*)malloc(sizeof(node_t));
memset(pNew, 0x00, sizeof(node_t));
strcpy(pNew->name, pd->d_name);
pNew->next = NULL;
if(NULL == pHead){
pHead = pNew;
}else{
//找待插入位置
node_t *pCur = pHead;
node_t *pPre = NULL;
while(pCur != NULL){
if(strcasecmp(pNew->name, pCur->name) > 0){
pPre = pCur;
pCur = pCur->next;
}else{
break;
}
}
if(NULL == pCur){
pPre->next = pNew;
}else if(NULL != pPre){
pPre->next = pNew;
pNew->next = pCur;
}else{
pHead = pNew;
pNew->next = pCur;
}
}
}
node_t *pCur = pHead;
while(pCur){
printf("%s\n", pCur->name);
pCur = pCur->next;
}
close(pDir);
}
完备的cp命令
cp src dst
可以是文件到文件,文件到目录,目录到目录
#include <stdio.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
void cp_file(const char *src, const char *dst, mode_t mode);
void cp_dir(const char *src , const char *dst);
int main( int argc, char *argv[] )
{
if (argc != 3) {
fprintf(stderr, "usage: %s src dst\n", argv[0]);
exit(1);
}
//stat判断文件类型以及是否存在
struct stat sbuf;
if (stat(argv[1], &sbuf) == -1 ) perror("stat src");
//src是文件
if (S_ISREG(sbuf.st_mode)) {
struct stat dbuf;
if ( stat(argv[2], &dbuf) == -1 ) {
// 目标不存在 可以直接复制
cp_file(argv[1], argv[2], sbuf.st_mode);
} else if (S_ISDIR(dbuf.st_mode)) { // 目标是目录
//拼接一个目标目录下的地址
char tmp[1024] = {};
sprintf(tmp, "%s/%s", argv[2], argv[1]);
cp_file(argv[1], tmp, sbuf.st_mode);
} else if (S_ISREG(dbuf.st_mode) ) { // 目标是已经存在的文件
printf("是否覆盖%s文件? ", argv[2]);
char ask = 'n';
scanf("%c", &ask);
if ( ask=='y' || ask=='Y' ) {
truncate(argv[2], 0); // 清空目标文件
cp_file(argv[1], argv[2], sbuf.st_mode);
}
}
}else if(S_ISDIR(sbuf.st_mode)) { // 原文件是目录
printf("源文件是目录 %d\n", S_ISDIR(sbuf.st_mode));
struct stat dbuf;
if ( stat(argv[2], &dbuf) == -1 ) { // 目标目录不存在
mkdir(argv[2], sbuf.st_mode); // 创建目标目录
char tmp[1024] = "";
sprintf(tmp, "%s/%s", argv[2], argv[1]);
mkdir(tmp, sbuf.st_mode);
cp_dir(argv[1], tmp);
} else if ( S_ISDIR(dbuf.st_mode) ) { // 目标是目录,作为子目录
char tmp[1024] = {};
sprintf(tmp, "%s/%s", argv[2], argv[1]);
cp_dir(argv[1], tmp);
} else { // 非法
printf("目录不能拷贝到文件中\n");
exit(0);
}
}
}
//将src文件拷贝到dst文件
void cp_file(const char *src, const char *dst, mode_t mode)
{
int fd_src = open(src, O_RDONLY);
if (fd_src == -1 ) perror("open src");
int fd_dst = open(dst, O_WRONLY|O_CREAT, mode);
if (fd_dst == -1 ) perror("open dst");
char buf[1024];
memset(buf, 0x00, sizeof(buf));
int r;
while ((r=read(fd_src, buf, 1024)) > 0 ) {
write(fd_dst, buf, r);
memset(buf, 0x00, sizeof(buf));
}
close(fd_src);
close(fd_dst);
}
//接受dst为目标目录
void cp_dir(const char *src , const char *dst)
{
DIR *pdir = opendir(src);
if ( pdir == NULL ) perror("opendir");
struct dirent *pd = NULL;
//循环将所有src目录下的内容拷贝
while ((pd=readdir(pdir)) != NULL ) {
if(strcmp(pd->d_name,".")==0 || strcmp(pd->d_name, "..")==0){
continue;
}
struct stat sbuf;
char srcTmp[1024] = "";
sprintf(srcTmp, "%s/%s", src, pd->d_name);
if(stat(srcTmp, &sbuf)== -1){
perror("stat ");
}
printf("当前处理的%s, 是目录吗%d\n",srcTmp, S_ISDIR(sbuf.st_mode));
if(S_ISDIR(sbuf.st_mode)){
//递归处理src下的子目录
char tmpDir[1024] = "";
sprintf(tmpDir, "%s/%s", dst, pd->d_name);
printf("在dst下创建的目录%s\n", tmpDir);
mkdir(tmpDir, sbuf.st_mode);
printf("递归传入的src:%s dst %s\n", srcTmp, tmpDir);
cp_dir(srcTmp, tmpDir);
continue;
}
//是普通文件
char dstTmp[1024];
sprintf(dstTmp, "%s/%s", dst, pd->d_name);
printf("普通文件源地址%s 目的文件名:%s\n", srcTmp, dstTmp);
cp_file(srcTmp, dstTmp, sbuf.st_mode);
}
close(pdir);
}