继续我的评论,大多数新的C程序员都感到困惑,因为他没有仔细考虑整个问题。你根本无法期望拨打rename并让它处理整个过程。 C库函数通常只做一件事,只有一件事。程序员应该从头到尾思考过程,并编写rename或readdir函数未提供的所有其他难题。
例如,如果你计划传递一个新的目录名称,你需要验证,你打算过移动文件的目录,是否确实存在(或者您需要创建它)。你如何测试新目录的存在?您还需要确定和验证格式为新的目录您将rename文件。它是否包含尾随'/'?如果它如何处理?
如果您只想移动具有特定扩展名的文件,则必须开发一种方法来检查并获取由readdir返回的每个文件名的扩展名。一旦我有当前文件的扩展名,我如何将它与目标扩展名进行比较?
最后,如何将我打算移动匹配文件的目录名与当前文件名结合起来以创建将文件移动到的完整路径?所有这些都是您需要提供的一些代码,以便能够将文件从一个目录移动到另一个目录。难以做到吗?不是。这很容易,但是您必须在该级别进行思考并提供最低数量的验证以确定您打算移动的任何单个文件的成功/失败。
而不是去探索如何创造每个单独的难题,因为我明白你需要帮助,而且它确实有助于有一个合理的“过去”来帮助你牢记各种难题,下面是一个简短的例子,它能够完成我理解你的问题的要求。下面以目录中搜索作为第一参数,扩展来搜索作为秒参数,并且相对或绝对路径名任何匹配的文件移动到作为第三参数(默认为.(搜索当前目录),用于文件名与"mkv"扩展,并移动到video子目录):
#include
#include
#include
#include /* PATH_MAX */
#include /* opendir */
#include /* opendir, readdir */
#include /* errno */
#include /* for file constants */
#include /* open/close */
int dir_exists (char *d);
char *fn_ext (char *fn);
char *fn_wext (char *s);
char *stripfwd (char *fn);
int main (int argc, char **argv) {
DIR *dp = opendir (argc > 1 ? argv[1] : ".");/* open directory (. default)*/
struct dirent *de = NULL; /* ptr to dirent for readdir */
char *srchext = argc > 2 ? argv[2] : "mkv", /* extension to search for */
*newdir = argc > 3 ? argv[3] : "./video",/* ptr newdir (video default)*/
path[PATH_MAX] = ""; /* array for trimmed newdir */
strcpy (path, newdir); /* copy newdir from read-only memory to array */
stripfwd (path); /* check for trailing '/' & overwrite with '\0' */
if (!dir_exists (path)) { /* validate new directory exists */
fprintf (stderr, "error: directory not found '%s'.\n", path);
return 0; /* or create/validate directory here */
}
while ((de = readdir (dp))) /* for each file in directory */
{
char *ext = NULL;
/* skip dot files */
if (!strcmp (de->d_name, ".") || !strcmp (de->d_name, ".."))
continue;
if ((ext = fn_ext (de->d_name)) == NULL) /* get file extension */
continue;
if (strcmp (srchext, ext) == 0) { /* if extensions match */
char newpath[PATH_MAX] = "", /* char array for newpath */
*fn = fn_wext (de->d_name); /* ptr to filename only */
sprintf (newpath, "%s/%s", path, fn); /* create newpath */
errno = 0;
if (rename (de->d_name, newpath) == -1) { /* rename/validate file */
fprintf (stderr, "error: move of '%s' to '%s' failed.\n",
de->d_name, newpath);
/* check errno here */
}
else /* output successful result */
printf ("moved '%s' to '%s'.\n", de->d_name, newpath);
}
}
return 0;
}
/** atomic test that directory exists (>=1 success, 0 otherwise)
* NOTE: no directory is actually created. fail occurs instead.
*/
int dir_exists (char *d)
{
int flags = O_DIRECTORY | O_RDONLY;
int mode = S_IRUSR | S_IWUSR;
int fd = open (d, flags, mode);
if (fd < 0) /* directory does not exist */
return 0;
else if (fd) { /* directory exists, rtn fd */
close (fd);
}
return fd;
}
/** Separates extension component from full filename string.
* Returns pointer following last '.' as extension, NULL otherwise.
* Protects against false return of ext followin '.' path.
* No memory is allocated, create copy of return to preserve.
*/
char *fn_ext (char *fn)
{
char *sp = NULL; /* start pointer */
char *ext;
if (!fn) return NULL;
if ((sp = strrchr (fn, '/'))) /* test for '/' to eliminate '.' in path */
sp++;
else
sp = fn;
if ((ext = strrchr (sp, '.')))
{
if (ext == fn) /* dot file case */
return NULL;
ext++;
}
else
ext = NULL;
return ext;
}
/** Separates filename component (with extension) from full filename string.
* Returns pointer following last '/' filename, full-string otherwise.
* No memory is allocated, create copy of return to preserve.
*/
char *fn_wext (char *s)
{
char *fn;
if ((fn = strrchr (s, '/')))
fn++;
else
fn = s;
return fn;
}
/** remove forward slash '/' at end of 'fn' */
char *stripfwd (char *fn)
{
size_t len = strlen (fn);
while (len && fn[len - 1] == '/')
fn[--len] = 0;
return fn;
}
实施例在当前目录的文件
$ l myvideo_*
-rw-r--r-- 1 david david 0 Apr 21 21:46 myvideo_1.mkv
-rw-r--r-- 1 david david 0 Apr 21 21:46 myvideo_2.mkv
-rw-r--r-- 1 david david 0 Apr 21 21:46 myvideo_3.mkv
-rw-r--r-- 1 david david 0 Apr 21 21:46 myvideo_4.mkv
-rw-r--r-- 1 david david 0 Apr 21 21:46 myvideo_5.mkv
空的 '视频' 目录
$ l video
total 28
drwxr-xr-x 2 david david 4096 Apr 21 21:45 .
drwxr-xr-x 15 david david 24576 Apr 21 21:46 ..
编译/构建
$ gcc -Wall -Wextra -pedantic -std=gnu11 -Ofast -o bin/readdir_rename readdir_rename.c
示例使用/输出
$ ./bin/readdir_rename . mkv video
moved 'myvideo_2.mkv' to 'video/myvideo_2.mkv'.
moved 'myvideo_1.mkv' to 'video/myvideo_1.mkv'.
moved 'myvideo_3.mkv' to 'video/myvideo_3.mkv'.
moved 'myvideo_4.mkv' to 'video/myvideo_4.mkv'.
moved 'myvideo_5.mkv' to 'video/myvideo_5.mkv'.
确认移动
$ l video
total 28
drwxr-xr-x 2 david david 4096 Apr 21 21:46 .
drwxr-xr-x 15 david david 24576 Apr 21 21:46 ..
-rw-r--r-- 1 david david 0 Apr 21 21:46 myvideo_1.mkv
-rw-r--r-- 1 david david 0 Apr 21 21:46 myvideo_2.mkv
-rw-r--r-- 1 david david 0 Apr 21 21:46 myvideo_3.mkv
-rw-r--r-- 1 david david 0 Apr 21 21:46 myvideo_4.mkv
-rw-r--r-- 1 david david 0 Apr 21 21:46 myvideo_5.mkv
看东西了,让我知道,如果你有任何问题。它本身并不难,但有很多需要考虑的是提供一个合理的强有力的举措(可以添加更多验证,这只是一个最小示例)。