Wenn ich von meinem Kommentar fortfahre, wo die meisten neuen C-Programmierer verwirrt werden, ist es, das gesamte Problem nicht zu durchdenken. Sie können einfach nicht erwarten, rename
aufrufen und es für den gesamten Prozess kümmern. Die C-Bibliotheksfunktionen machen im Allgemeinen eine Sache und nur eine Sache. Es liegt am Programmierer, den Prozess von Anfang bis Ende zu denken und alle zusätzlichen Teile des Puzzles zu codieren, die nicht durch die Funktionen rename
oder readdir
bereitgestellt werden.
Wenn Sie nur Dateien mit einer spezifischen Extension verschieben möchten, müssen Sie eine Möglichkeit zum Suchen und Abrufen der Erweiterung von jedem von zurückgegebenen Dateinamen entwickeln. Sobald ich die Erweiterung für die aktuelle Datei habe, wie vergleiche ich sie mit der Zielerweiterung?
Schließlich, wie kombiniere ich den Verzeichnisnamen Ich beabsichtige, passende Dateien zu verschieben, mit dem aktuellen Dateinamen, um den vollständigen Pfad zu erstellen, um die Dateien zu verschieben? All dies sind Code-Bits, die Sie bereitstellen müssen, um Dateien von einem Verzeichnis in ein anderes zu verschieben. Ist es schwer zu tun? Nein. Es ist ziemlich einfach, aber Sie müssen auf dieser Ebene durchdenken und eine Mindestanzahl von Validierung geben, um Erfolg/Misserfolg einer einzelnen Datei zu bestimmen, die Sie verschieben möchten.
Anstatt zu gehen, wie man jedes einzelne Teil des Puzzles erstellt, weil ich verstehe, dass Sie Hilfe brauchen, und es hilft, ein vernünftiges "go-by" zu haben, um die verschiedenen Teile des Puzzles in Ihrem Verstand zu zementieren Das folgende ist ein kurzes Beispiel, das das ausführt, was ich verstehe Ihre Frage fragt. Im Folgenden ist der Verzeichnis als ersten Argument zu suchen, die Verlängerungs für als zweiten Argument zu suchen, und dem relativen oder absolute Pfadname keine passenden Dateien als dritten Argument zu bewegen (die Standardwerte sind .
(aktuelles Verzeichnis suchen) für Dateinamen mit "mkv"
Erweiterungen und auf das Unterverzeichnis video
bewegen):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h> /* PATH_MAX */
#include <sys/types.h> /* opendir */
#include <dirent.h> /* opendir, readdir */
#include <errno.h> /* errno */
#include <fcntl.h> /* for file constants */
#include <unistd.h> /* 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;
}
Beispiel Dateien im aktuellen Verzeichnis
$ 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
Leere 'video' Verzeichnis
$ 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 ..
Compile/Build
$ gcc -Wall -Wextra -pedantic -std=gnu11 -Ofast -o bin/readdir_rename readdir_rename.c
Beispiel Verwendung/Output
$ ./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'.
Verschieben bestätigen
$ 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
Blick über Dinge und lassen Sie mich wissen, wenn Sie Fragen haben. Nichts davon ist schwer für sich allein, aber es gibt eine ganze Menge zu überlegen, um eine einigermaßen robuste Bewegung zu ermöglichen (es gibt viele weitere Validierungen, die Sie hinzufügen können, dies ist als ein minimales Beispiel gedacht).
Sie können Formatbezeichner * nicht an 'rename' übergeben (z. B.'% s' ergibt keinen Sinn in 'rename'). Verwenden Sie 'sprintf' oder' snprintf', um den 'newpath' für' scarface.mkv' zu erstellen und übergeben Sie die verkettete Zeichenfolge an 'rename'. Der Prototyp für 'rename' ist' int rename (const char * oldpath, const char * newpath); 'Es liegt an dir, * nul-terminated *' oldpath' und 'newpath' richtig zu erstellen.('man 2 rename' ist dein Freund) –