C :: Aufgabe #65
3 Lösungen
Programm für Dateisuche (Dateifilter)
Anfänger - C
von devnull
- 29.11.2014 um 08:17 Uhr
Realisiere einen Dateifilter. Das Programm soll einen Verzeichnispfad und eine Namenserweiterung , z.B. ".txt" abfragen und alle dazu passenden Dateien aus dem Verzeichnis auflisten (Dateiname genügt).
Erweiterung: es soll möglich sein mit einem Muster, z.B. "*log.[1-3].gz" nach Dateien zu suchen.
Erweiterung: es soll möglich sein mit einem Muster, z.B. "*log.[1-3].gz" nach Dateien zu suchen.
Lösungen:
Variante 1: Suche über Dateinamenserweiterung (Extension)
C-Code
Konsolenausgabe:
$ ./filter /var/log .log
dpkg.log
alternatives.log
pm-suspend.log
user.log
auth.log
...
/*****************************************
* filter.c Dateifilter (File-Extension)
*****************************************/
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#define PATH_LEN 255
#define EXT_LEN 31
int main(int argc, char **argv) {
DIR* dir;
struct dirent *dire;
char dirpath[PATH_LEN+1];
char filext[EXT_LEN+1];
char *fp;
int lext;
if (argc > 2) {
strncpy(dirpath, argv[1], PATH_LEN);
strncpy(filext, argv[2], EXT_LEN);
} else {
printf("Verzeichnispfad: ");
scanf("%s", dirpath);
printf("Datei-Extension: ");
scanf("%s", filext);
}
// max. length of file extension
lext = strlen(filext);
if (lext > EXT_LEN)
lext = EXT_LEN;
// open directory
if ((dir = opendir(dirpath)) == NULL) {
fprintf(stderr, "cannot open '%s': %s\n", dirpath,\
strerror(errno));
return 1;
}
// read directory
while ((dire = readdir(dir)) != NULL) {
if (errno > 0) {
fprintf(stderr, "error while reading directory entry: %s\n",\
strerror(errno));
break;
}
fp = dire->d_name + strlen(dire->d_name) - lext;
if (strcmp(fp, filext) == 0)
printf("%s\n", dire->d_name);
}
// close directory
closedir( dir );
return 0;
}
Die zweite Lösung für den Dateifilter verwendet reguläre Ausdrücke (mit Option -E Extended Regex, sonst Basic Regex).
Beispiele:
C-Code
Beispiele:
Konsolenausgabe:
$ ./filter2 /usr/include 'term.*\.h'
termios.h
term.h
termio.h
term_entry.h
termcap.h
$ ./filter2 -E /var/log '^[a-z]{4}\.log\.[23]\.gz'
kern.log.2.gz
user.log.3.gz
kern.log.3.gz
auth.log.2.gz
user.log.2.gz
dpkg.log.2.gz
dpkg.log.3.gz
auth.log.3.gz
/*****************************************
* filter2.c Dateifilter (Regex Match)
*****************************************/
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
#include <regex.h>
#define PATH_LEN 255
#define REGX_LEN 255
int main(int argc, char **argv) {
regex_t regex;
DIR* dir;
struct dirent *dire;
char dirpath[PATH_LEN+1];
char pattern[REGX_LEN+1];
int opt_ere=0, opt_ind=1;
if (argc < 3)
return 1;
else {
if (argc == 4 && argv[1][0] == '-' && argv[1][1] == 'E') {
opt_ere = 1;
opt_ind = 2;
}
strncpy(dirpath, argv[opt_ind], PATH_LEN);
strncpy(pattern, argv[opt_ind+1], REGX_LEN);
}
// compile extended regular expression
if (regcomp(®ex, pattern, (opt_ere?REG_EXTENDED:0)|REG_NOSUB) != 0) {
fprintf( stderr, "could not compile regex\n" );
return 2;
}
// open directory
if ((dir = opendir(dirpath)) == NULL) {
fprintf(stderr, "cannot open '%s': %s\n", dirpath,\
strerror(errno));
return 3;
}
// read directory
while ((dire = readdir(dir)) != NULL) {
if (errno > 0) {
fprintf(stderr, "error while reading directory entry: %s\n",\
strerror(errno));
break;
}
if (regexec(®ex, dire->d_name, 0, NULL, 0) == 0)
printf("%s\n", dire->d_name);
}
closedir( dir );
regfree(®ex);
return 0;
}
Die dritte Lösung für den Dateifilter verwendet Path-Globbing analog zur (Unix/Linux-)Shell-Kommandozeile. Die Ergebnisse werden sortiert ausgegeben:
Beispiel:
C-Code
Beispiel:
Konsolenausgabe:
$ ./filter /usr/include '[ab]*.h'
aio.h
aliases.h
alloca.h
ar.h
argp.h
argz.h
assert.h
byteswap.h
/*****************************************
* filter3.c Dateifilter (Glob Match)
*****************************************/
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <glob.h>
#define PATH_LEN 255
#define GLOB_LEN 255
int main(int argc, char **argv) {
char dirpath[PATH_LEN+1];
char pattern[GLOB_LEN+1];
glob_t globbuf;
int cp;
if (argc < 2) {
fprintf(stderr, "Usage: ./filter <Pfad> <Muster>\n");
return 1;
}
strncpy(dirpath, argv[1], PATH_LEN);
strncpy(pattern, argv[2], GLOB_LEN);
if (chdir(dirpath) != 0)
fprintf(stderr, "chdir %s: %s\n", dirpath, strerror(errno));
// do path globbing and read matched paths
glob(pattern, 0, NULL, &globbuf);
for (cp=0; cp < globbuf.gl_pathc; cp++) {
if (globbuf.gl_pathv[cp] != NULL)
printf("%s\n", globbuf.gl_pathv[cp]);
}
globfree(&globbuf);
return 0;
}
