rm(Remove)
rmコマンドに似せたものを作りました.
再帰を利用しています. 後に詳しく説明をします.
/* Pseudo rm command
* Author: Jin
* Ver: 1.0.3
* ****************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<dirent.h>
#include<fcntl.h>
#include<unistd.h>
#include<getopt.h>
static struct option long_options[] = {
{"recursive", required_argument, 0, 'r'},
{"help", no_argument , 0, 'h'},
{"version", no_argument , 0, 'v'},
{0, 0, 0, 0},
};
static char *name = "rm";
extern char *optarg;
extern int optind, opterr, optopt;
static void help(const char *path);
static void version(void);
static void do_remove(const char *path);
static void recursive_rm(const char *path);
static void rm_err(const char *path);
int main(int argc, char **argv)
{
if(argc < 2) {
help(argv[0]);
exit(0);
}
int i;
int opt, option_index = 0;
int f_ver, f_help, f_rec;
f_rec = 0;
f_help = 0;
f_ver = 0;
while((opt = getopt_long(argc, argv, "vhrRia:", long_options, &option_index)) != EOF) {
switch(opt) {
case 'r':
f_rec = 1;
break;
case 'R':
f_rec = 1;
break;
case 'h':
f_help = 1;
break;
case 'v':
f_ver = 1;
break;
case '?':
f_help = 1;
break;
default:
f_help = 1;
break;
}
}
if(f_help || f_ver) {
if(f_help) help(argv[0]);
if(f_ver) version();
exit(0);
}
else if(f_rec) {
if(argc == 2)
rm_err(name);
for(i = 2; i < argc; i++) {
recursive_rm(argv[i]);
}
}
if(f_rec == 0 && f_help == 0 && f_ver == 0)
for(i = 1; i < argc; i++)
do_remove(argv[i]);
return 0;
}
static void help(const char *path) {
printf("Usage: %s [Option] [Filename]...\n", path);
printf("ファイルを削除します.(ディレクトリは無効)\n\n");
printf("\t-r, -R, --recursive: ディレクトリを含む全てを削除\n");
printf("\t-h, --help: ヘルプを表示\n");
printf("\t-v, --version: バージョンを表示\n\n");
printf("%sではディレクトリを削除できません. ディレクトリを含め全てを削除したい場合は`--recursive`,(もしくは, -r -R)をオプションで指定してください.\n\n", name);
}
static void version(void) {
printf("Version: 1.0.3\n");
}
static void do_remove(const char *path) {
if(unlink(path) == EOF) {
perror("unlink");
exit(1);
}
}
static void recursive_rm(const char *path) {
char buff[128] = "\0";
if(chdir(path) == EOF) {
perror("Change Directory");
exit(1);
}
if(getcwd(buff, 127) == NULL) {
perror("getcwd");
exit(1);
}
if(strlen(buff) > 127) {
perror("Overname");
exit(1);
}
DIR *opd;
struct dirent *rddir;
struct stat st;
if((opd = opendir(buff)) == NULL) {
perror("opendir");
exit(1);
}
while((rddir = readdir(opd)) != NULL) {
if(stat(rddir->d_name, &st) == EOF) {
perror("Stat");
closedir(opd);
exit(1);
}
if(S_ISDIR(st.st_mode)) {
if(rmdir(rddir->d_name) == EOF) {
if(strcmp(rddir->d_name, ".") && strcmp(rddir->d_name, "..")) {
recursive_rm(rddir->d_name);
}
}
}
if(unlink(rddir->d_name) == EOF);
}
if(rmdir(buff) == EOF) {
perror("rmdir");
}
if(closedir(opd) == EOF) {
perror("Closedir");
exit(1);
}
}
static void rm_err(const char *path) {
printf("%s: ファイル名を指定してください.\n", path);
printf("詳しくは`rm --help`を実行してください.\n");
exit(1);
}
実行例:
$ ./rm --help
Usage: rm [Option] [Filename]...
ファイルを削除します.(ディレクトリは無効)
-r, -R, --recursive: ディレクトリを含む全てを削除
-h, --help: ヘルプを表示
-v, --version: バージョンを表示
rmではディレクトリを削除できません. ディレクトリを含め全てを削除したい場合は`--recursive`,(もしくは, -r -R)をオプションで指定してください.