diff --git a/main.c b/main.c
index 51d97d4..ada0574 100644
--- a/main.c
+++ b/main.c
@@ -104,6 +104,12 @@ int main(int argc, char **argv) {
 
 	parse_options(argc, argv);
 
+	if (options->clean_cache) {
+		tns_init(&tns, 0);
+		tns_clear_cache(&tns);
+		exit(0);
+	}
+
 	if (!options->filecnt) {
 		print_usage();
 		exit(1);
diff --git a/options.c b/options.c
index f5066f4..8105485 100644
--- a/options.c
+++ b/options.c
@@ -31,7 +31,7 @@ options_t _options;
 const options_t *options = (const options_t*) &_options;
 
 void print_usage() {
-	printf("usage: sxiv [-adFfhpqrstvZ] [-g GEOMETRY] [-z ZOOM] FILES...\n");
+	printf("usage: sxiv [-aCdFfhpqrstvZ] [-g GEOMETRY] [-z ZOOM] FILES...\n");
 }
 
 void print_version() {
@@ -53,9 +53,10 @@ void parse_options(int argc, char **argv) {
 
 	_options.all = 0;
 	_options.quiet = 0;
+	_options.clean_cache = 0;
 	_options.recursive = 0;
 
-	while ((opt = getopt(argc, argv, "adFfg:hpqrstvZz:")) != -1) {
+	while ((opt = getopt(argc, argv, "aCdFfg:hpqrstvZz:")) != -1) {
 		switch (opt) {
 			case '?':
 				print_usage();
@@ -63,6 +64,9 @@ void parse_options(int argc, char **argv) {
 			case 'a':
 				_options.all = 1;
 				break;
+			case 'C':
+				_options.clean_cache = 1;
+				break;
 			case 'd':
 				_options.scalemode = SCALE_DOWN;
 				break;
diff --git a/options.h b/options.h
index c32b50a..b7b8ba5 100644
--- a/options.h
+++ b/options.h
@@ -37,6 +37,7 @@ typedef struct {
 
 	unsigned char all;
 	unsigned char quiet;
+	unsigned char clean_cache;
 	unsigned char recursive;
 } options_t;
 
diff --git a/thumbs.c b/thumbs.c
index 2e28908..abcfaaa 100644
--- a/thumbs.c
+++ b/thumbs.c
@@ -71,7 +71,10 @@ Imlib_Image* tns_cache_load(const char *filename) {
 	struct stat cstats, fstats;
 	Imlib_Image *im = NULL;
 
-	if (!filename || stat(filename, &fstats))
+	if (!filename)
+		return NULL;
+
+	if (stat(filename, &fstats))
 		return NULL;
 
 	if ((cfile = tns_cache_filename(filename))) {
@@ -97,6 +100,7 @@ void tns_cache_write(thumb_t *t, Bool force) {
 
 	if (!t || !t->im || !t->filename)
 		return;
+
 	if (stat(t->filename, &fstats))
 		return;
 
@@ -130,6 +134,40 @@ void tns_cache_write(thumb_t *t, Bool force) {
 	}
 }
 
+void tns_clear_cache(tns_t *tns) {
+	int dirlen, delete;
+	char *cfile, *filename, *tpos;
+	r_dir_t dir;
+
+	if (!cache_dir)
+		return;
+	
+	if (r_opendir(&dir, cache_dir)) {
+		warn("could not open thumbnail cache directory: %s", cache_dir);
+		return;
+	}
+
+	dirlen = strlen(cache_dir);
+
+	while ((cfile = r_readdir(&dir))) {
+		filename = cfile + dirlen;
+		delete = 0;
+
+		if ((tpos = strrchr(filename, '.'))) {
+			*tpos = '\0';
+			delete = access(filename, F_OK);
+			*tpos = '.';
+		}
+
+		if (delete && unlink(cfile))
+			warn("could not delete cache file: %s", cfile);
+
+		free(cfile);
+	}
+
+	r_closedir(&dir);
+}
+
 
 void tns_init(tns_t *tns, int cnt) {
 	int len;
@@ -138,9 +176,14 @@ void tns_init(tns_t *tns, int cnt) {
 	if (!tns)
 		return;
 
+	if (cnt) {
+		tns->thumbs = (thumb_t*) s_malloc(cnt * sizeof(thumb_t));
+		memset(tns->thumbs, 0, cnt * sizeof(thumb_t));
+	} else {
+		tns->thumbs = NULL;
+	}
+
 	tns->cnt = tns->first = tns->sel = 0;
-	tns->thumbs = (thumb_t*) s_malloc(cnt * sizeof(thumb_t));
-	memset(tns->thumbs, 0, cnt * sizeof(thumb_t));
 	tns->cap = cnt;
 	tns->dirty = 0;
 
@@ -150,25 +193,28 @@ void tns_init(tns_t *tns, int cnt) {
 		len = strlen(homedir) + 10;
 		cache_dir = (char*) s_malloc(len * sizeof(char));
 		snprintf(cache_dir, len, "%s/.sxiv", homedir);
+	} else {
+		warn("could not locate thumbnail cache directory");
 	}
 }
 
 void tns_free(tns_t *tns, win_t *win) {
 	int i;
 
-	if (!tns || !tns->thumbs)
+	if (!tns)
 		return;
 
-	for (i = 0; i < tns->cnt; ++i) {
-		if (tns->thumbs[i].im) {
-			imlib_context_set_image(tns->thumbs[i].im);
-			imlib_free_image();
+	if (tns->thumbs) {
+		for (i = 0; i < tns->cnt; ++i) {
+			if (tns->thumbs[i].im) {
+				imlib_context_set_image(tns->thumbs[i].im);
+				imlib_free_image();
+			}
 		}
+		free(tns->thumbs);
+		tns->thumbs = NULL;
 	}
 
-	free(tns->thumbs);
-	tns->thumbs = NULL;
-
 	if (cache_dir) {
 		free(cache_dir);
 		cache_dir = NULL;
@@ -182,7 +228,7 @@ void tns_load(tns_t *tns, win_t *win, int n, const char *filename) {
 	thumb_t *t;
 	Imlib_Image *im;
 
-	if (!tns || !win || !filename)
+	if (!tns || !tns->thumbs || !win || !filename)
 		return;
 
 	if (n >= tns->cap)
@@ -265,7 +311,10 @@ void tns_render(tns_t *tns, win_t *win) {
 	int i, cnt, r, x, y;
 	thumb_t *t;
 
-	if (!tns || !tns->dirty || !win)
+	if (!tns || !tns->thumbs || !win)
+		return;
+
+	if (!tns->dirty)
 		return;
 
 	win_clear(win);
@@ -313,7 +362,7 @@ void tns_highlight(tns_t *tns, win_t *win, int n, Bool hl) {
 	thumb_t *t;
 	unsigned long col;
 
-	if (!tns || !win)
+	if (!tns || !tns->thumbs || !win)
 		return;
 
 	if (n >= 0 && n < tns->cnt) {
@@ -336,7 +385,7 @@ void tns_highlight(tns_t *tns, win_t *win, int n, Bool hl) {
 int tns_move_selection(tns_t *tns, win_t *win, tnsdir_t dir) {
 	int old;
 
-	if (!tns || !win)
+	if (!tns || !tns->thumbs || !win)
 		return 0;
 
 	old = tns->sel;
@@ -395,7 +444,10 @@ int tns_translate(tns_t *tns, int x, int y) {
 	int n;
 	thumb_t *t;
 
-	if (!tns || x < tns->x || y < tns->y)
+	if (!tns || !tns->thumbs)
+		return -1;
+
+	if (x < tns->x || y < tns->y)
 		return -1;
 
 	n = tns->first + (y - tns->y) / thumb_dim * tns->cols +
diff --git a/thumbs.h b/thumbs.h
index 60e7e7b..4a8af09 100644
--- a/thumbs.h
+++ b/thumbs.h
@@ -52,6 +52,8 @@ typedef struct {
 	unsigned char dirty;
 } tns_t;
 
+void tns_clear_cache(tns_t*);
+
 void tns_init(tns_t*, int);
 void tns_free(tns_t*, win_t*);