Unix:将文件从当前目录复制到C中的另一个目录
我正在尝试制作一个复制程序,允许我将文件从当前目录复制到另一个目录。 到目前为止,我正在使用open()、create()、read()、write() 例如: 到目前为止,我只能将文件复制到当前目录 我有一个文件夹名a_文件夹和一个文件名file_1,我想将file_1从我的当前目录复制到a_文件夹 有人能帮我吗 代码和图像如下所示 我现在能做的是: /复制文件1复制文件 我想要的是: /复制文件1/文件夹复制文件Unix:将文件从当前目录复制到C中的另一个目录,c,linux,unix,directory,copy,C,Linux,Unix,Directory,Copy,我正在尝试制作一个复制程序,允许我将文件从当前目录复制到另一个目录。 到目前为止,我正在使用open()、create()、read()、write() 例如: 到目前为止,我只能将文件复制到当前目录 我有一个文件夹名a_文件夹和一个文件名file_1,我想将file_1从我的当前目录复制到a_文件夹 有人能帮我吗 代码和图像如下所示 我现在能做的是: /复制文件1复制文件 我想要的是: /复制文件1/文件夹复制文件 如果给定a\u文件夹和file\u 1,则需要一个帮助函数来构造所需的路径 此
a\u文件夹
和file\u 1
,则需要一个帮助函数来构造所需的路径
此类函数的一个典型示例是
char *combine_path(const char *dir, const char *name)
{
/* Calculate the lengths of the path components.
If the respective parameter is NULL, the length is zero .*/
const size_t dirlen = (dir) ? strlen(dir) : 0;
const size_t namelen = (name) ? strlen(name) : 0;
char *path, *p;
/* We allocate <dir> + '/' + <name> + '\0'. */
path = malloc(dirlen + namelen + 2);
if (!path) {
errno = ENOMEM;
return NULL;
}
/* Let p point to the current position in the
resulting path. */
p = path;
/* If there is a directory part,
copy it, and append a '/' after it. */
if (dirlen > 0) {
memcpy(p, dir, dirlen);
p += dirlen;
*p = '/';
p += 1;
}
/* If there is a name part, copy it. */
if (namelen > 0) {
memcpy(p, name, namelen);
p += namelen;
}
/* Append a NUL char, '\0', to terminate the
dynamically allocated buffer.
This turns it into a C string. */
*p = '\0';
/* Return the pointer to the dynamically-allocated
memory, containing the concatenated paths
as a single string. */
return path;
}
请注意我如何使用p
和q
指针将读取缓冲区内容写入可能不止一个部分的模式。如果源文件是本地文件,而目标文件位于某个不稳定的文件系统上,则可能会发生这种情况。不要求write()
写入整个缓冲区或返回错误代码;短写(只写了给定缓冲区中的一些初始数据)是完全可以的,并且在某些情况下确实会发生。以上是我处理这些问题的首选方法
很多人都考虑过这样的错误检查级别——尤其是检查<代码>关闭()/<代码>的结果值,因为在这个时间点,许多操作系统(包括Linux)从不在那里返回错误——愚蠢的或至少偏执的。 我个人认为这种错误检查“稳健”,因为我希望我的代码告诉我,作为用户,如果有任何不愉快的事情发生;我绝对不希望它只是假设一切顺利,我希望它是偏执的。(我并不是说OP的代码不检查错误代码;我只是说这个版本在这方面更加谨慎和直言不讳。)
请问
av
是如何定义和初始化/设置的?好的,我已经更新了,您想在调用fprintf()
之前调用perror()
,以避免误导输出表单perror()
。我没有任何错误,我只是不知道如何将文件复制到另一个目录中。我已经重新更新了。谢谢你的帮助,我会尝试一下。你介意更详细地解释解决方案1吗?有些功能超出了我的理解范围。X(@mmm:I重新注释了combine_path()
函数。您现在能理解它吗?您可以在命令行上找到和的文档,即运行man 3 malloc
,man 3 strlen
,或man 3 memcpy
。@mmm:不幸的是,没有——但我喜欢您的态度:)。网上的大多数教程和指南都很差。不过,您可以在教程中查找两件事。当逐行阅读输入时,一个好的教程应该展示如何使用POSIX.1-2008来完成。在处理网络连接时,本教程应使用。任何涉及这些主题但使用其他内容的教程都不值得阅读。
int copy_file(const char *frompath, const char *topath)
{
struct stat frominfo, toinfo;
char data[BUFFERSIZE];
ssize_t n;
int src, dst, cause;
if (!frompath || !*frompath ||
!*topath || !*topath) {
fprintf(stderr, "copy_file(): NULL or empty file name!\n");
return errno = EINVAL;
}
src = open(frompath, O_RDONLY | O_NOCTTY);
if (src == -1) {
cause = errno;
fprintf(stderr, "%s: Cannot open file: %s.\n", frompath, strerror(cause));
return errno = cause;
}
if (fstat(src, &frominfo) == -1) {
cause = errno;
fprintf(stderr, "%s: Cannot get file statistics: %s.\n", frompath, strerror(cause));
return errno = cause;
}
dst = open(topath, O_WRONLY | O_CREAT | O_EXCL, frominfo.st_mode & 0777);
if (dst == -1) {
cause = errno;
fprintf(stderr, "%s: Cannot create file: %s.\n", topath, strerror(saved_errno));
errno = cause;
}
while (1) {
char *p, *q;
n = read(src, buffer, sizeof buffer);
if (n == 0) {
/* End of input. */
cause = 0;
break;
} else
if (n < 0) {
/* Error (or interrupt, EINTR). */
if (n == -1)
cause = errno;
else
cause = EIO; /* n < -1 is a bug. */
fprintf(stderr, "%s: Read error: %s.\ņ", frompath, strerror(cause));
break;
}
p = buffer;
q = n;
cause = 0;
while (p < q) {
n = write(dst, p, (size_t)(q - p));
if (n > 0)
p += n;
else
if (n == -1) {
cause = errno;
break;
else {
/* Bug; should never occur. */
cause = EIO;
break;
}
}
if (cause) {
fprintf(stderr, "%s: Write error: %s.\n", topath, strerror(cause));
break;
}
}
/* Failed? */
if (cause) {
unlink(topath);
return errno = cause;
}
if (fstat(dst, &toinfo) == -1) {
cause = errno;
fprintf(stderr, "%s: Cannot get file information: %s.\n", topath, strerror(cause));
unlink(topath);
return errno = cause;
}
/* from may be a device; if so, its size
will be zero. */
if (frominfo.st_size > 0 &&
frominfo.st_size != toinfo.st_size) {
cause = EIO;
fprintf(stderr, "%s: File size mismatch!\n", topath);
unlink(topath);
return errno = cause;
}
/* Careful closing. */
if (close(src) == -1) {
cause = errno;
fprintf(stderr, "%s: Error closing file: %s.\n", frompath, strerror(cause));
unlink(topath);
return errno = cause;
}
if (close(dst) == -1) {
cause = errno;
fprintf(stderr, "%s: Error closing file: %s.\n", topath, strerror(cause));
unlink(topath);
return errno = cause;
}
/* Success. */
return errno = 0;
}