diff --git a/libmu/file_open.c b/libmu/file_open.c
new file mode 100644
index 0000000..f0fb082
--- /dev/null
+++ b/libmu/file_open.c
@@ -0,0 +1,16 @@
+#include "file_open.h"
+
+FILE *file_open(const char *prog, const char *path, const char *mode) {
+	if (!strcmp(path, "-"))
+		return stdin;
+
+	FILE *fp = fopen(path, mode);
+	if (fp == NULL) {
+		if (prog)
+			fprintf(stderr, "%s: %s\n", prog, strerror(errno));
+
+		return NULL;
+	}
+
+	return fp;
+}
diff --git a/libmu/file_open.h b/libmu/file_open.h
new file mode 100644
index 0000000..6832558
--- /dev/null
+++ b/libmu/file_open.h
@@ -0,0 +1,9 @@
+#ifndef _FILE_OPEN_H
+#define _FILE_OPEN_H
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+FILE *file_open(const char *prog, const char *path, const char *mode);
+#endif
diff --git a/src/cmp.c b/src/cmp.c
index 0b7a26d..a23f909 100644
--- a/src/cmp.c
+++ b/src/cmp.c
@@ -3,7 +3,8 @@
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
-static char s_flag;
+#include "file_open.h"
+static char *s_flag = "cmp";
 
 static int compare(FILE *fp1, FILE *fp2, const char *s1, const char *s2) {
 	if (fp1 == fp2)
@@ -29,7 +30,7 @@ static int compare(FILE *fp1, FILE *fp2, const char *s1, const char *s2) {
 		}
 
 		else if (ch1 != ch2) {
-			if (!s_flag)
+			if (s_flag)
 				printf("files differ at byte %zu and line %zu\n", byte, lines);
 
 			return 1;
@@ -55,26 +56,13 @@ static long parse_int(const char *str) {
 	return val;
 }
 
-static FILE *file_open(const char *path) {
-	if (!strcmp(path, "-"))
-		return stdin;
-
-	FILE *fp = fopen(path, "r");
-	if (fp == NULL) {
-		fprintf(stderr, "cmp: %s\n", strerror(errno));
-		return NULL;
-	}
-
-	return fp;
-}
-
 int main(int argc, char **argv) {
 
 	int opt;
 	while ((opt = getopt(argc, argv, "s")) != -1) {
 		switch (opt) {
 			case 's':
-				s_flag = 1;
+				s_flag = NULL;
 				break;
 
 			default:
@@ -106,7 +94,7 @@ int main(int argc, char **argv) {
 
 		case 2:
 			s2 = argv[1];
-			fp2 = file_open(argv[1]);
+			fp2 = file_open(s_flag, argv[1], "r");
 			if (fp2 == NULL)
 				exit(1);
 
@@ -114,7 +102,7 @@ int main(int argc, char **argv) {
 
 		case 1:
 			s1 = argv[0];
-			fp1 = file_open(argv[0]);
+			fp1 = file_open(s_flag, argv[0], "r");
 			if (fp1 == NULL) {
 				fclose(fp2);
 				exit(1);
@@ -128,14 +116,14 @@ int main(int argc, char **argv) {
 	}
 
 	if (skip1 && fseek(fp1, skip1, SEEK_SET) < 0) {
-		if (!s_flag)
+		if (s_flag)
 			fprintf(stderr, "cmp: %s\n", strerror(errno));
 
 		return 1;
 	}
 
 	if (skip2 && fseek(fp2, skip2, SEEK_SET) < 0) {
-		if (!s_flag)
+		if (s_flag)
 			fprintf(stderr, "cmp: %s\n", strerror(errno));
 
 		return 1;
diff --git a/src/sh.c b/src/sh.c
deleted file mode 100644
index ae8ae14..0000000
--- a/src/sh.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include "replace.h"
-
-enum {
-	NONE,
-	QUOTE
-};
-
-typedef {
-	char **argv;
-	size_t argc;
-
-	int stdin;
-	int stdout;
-	int stderr;
-};
-
-char **parse(char **str, size_t *size) {
-	size_t count = 1;
-	char *p = *str;
-
-	while (*p) {
-		if (*p == ' ')
-			count++;
-
-		p++;
-	}
-
-	char **tok = malloc((count + 1) * sizeof(char *));
-	if (tok == NULL) {
-		fprintf(stderr, "sh: malloc: %s\n", strerror(errno));
-		return NULL;
-	}
-
-	*size = 0;
-	p = strtok(*str, " \t\n\r\a");
-	while (p != NULL) {
-		tok[*size] = strdup(p);
-		(*size)++;
-
-		p = strtok(NULL, " \t\n\r\a");
-	}
-
-	tok[*size] = NULL;
-	return tok;
-}
-
-int main(int argc, char **argv) {
-	int opt;
-	while ((opt = getopt(argc, argv, "l")) != -1) {
-		switch (opt) {
-			case 'l':
-				break;
-
-			default:
-				puts("sh [l]\n\t-l Login");
-				break;
-		}
-	}
-
-	int ret = 1;
-
-	char *string = NULL;
-	size_t n = 0;
-	ssize_t bytes = 0;
-
-	while ((bytes = getline(&string, &n, stdin)) > 0) {
-		size_t size = 0;
-		char **tok = parse(&string, &size);
-
-		for (size_t i = 0; i < size; i++)
-			puts(tok[i]);
-
-		clear_parser(tok);
-	}
-
-	ret = 0;
-
-CLOSE:
-	if (string)
-		free(string);
-
-	return ret;
-}
-*/
diff --git a/src/shuf.c b/src/shuf.c
new file mode 100644
index 0000000..7170106
--- /dev/null
+++ b/src/shuf.c
@@ -0,0 +1,138 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <time.h>
+#include "file_open.h"
+
+struct STRINGS {
+	size_t lines;
+	char **buf;
+} str;
+size_t n_flag;
+FILE *o_flag;
+
+void free_strings(char print_flag) {
+	if (str.buf == NULL)
+		return;
+
+	size_t num = 0;
+	for (size_t i = 0; i <= str.lines; i++)
+		if (str.buf[i] != NULL) {
+			if (print_flag) {
+				if (n_flag == 0)
+					fprintf(o_flag, "%s", str.buf[i]);
+
+				else if (num < n_flag) {
+					size_t r = rand() % str.lines;
+					fprintf(o_flag, "%s", str.buf[r]);
+					num++;
+				}
+			}
+
+			free(str.buf[i]);
+		}
+
+	free(str.buf);
+}
+
+static char read_file(FILE *fp) {
+	char *line = NULL;
+	ssize_t bytes = 0;
+	size_t n = 0;
+
+	str.buf = malloc(sizeof(char *));
+	if (str.buf == NULL)
+		goto RF_ERROR;
+
+	while ((bytes = getline(&line, &n, fp)) != -1) {
+		char **tmp = realloc(str.buf, sizeof(char *) * (str.lines + 2));
+		if (tmp == NULL)
+			goto RF_ERROR;
+
+		str.buf = tmp;
+
+		str.buf[str.lines] = strdup(line);
+		if (str.buf[str.lines] == NULL)
+			goto RF_ERROR;
+
+		str.lines++;
+
+	}
+
+	if (line)
+		free(line);
+
+	return 0;
+
+RF_ERROR:
+	fprintf(stderr, "shuf: read file: %s\n", strerror(errno));
+	free_strings(0);
+	return 1;
+}
+
+int main(int argc, char **argv) {
+	srand(time(NULL));
+	o_flag = stdout;
+
+	char *p;
+	int opt;
+	while ((opt = getopt(argc, argv, "o:n:")) != -1) {
+		switch (opt) {
+			case 'o':
+				o_flag = file_open("shuf", optarg, "w");
+				if (o_flag == NULL)
+					return 1;
+
+				break;
+
+			case 'n':
+				n_flag = strtoul(optarg, &p, 10);
+				break;
+
+			default:
+				printf("shuf -[on]\n\t-n NUM Output at most NUM lines\n\t-o STR Write to FILE\n");
+				return 0;
+		}
+	}
+
+	argv += optind;
+	argc -= optind;
+
+	char *file = argv[0];
+	if (argc == 0)
+		file = "-";
+
+	FILE *fp = file_open("shuf", file, "r");
+	if (fp == NULL)
+		goto ERROR;
+
+	if (read_file(fp) == 1)
+		goto ERROR;
+
+	/* Shuf */
+	if (n_flag == 0) {
+		for (size_t i = 0; i < str.lines; i++) {
+			char *tmp = str.buf[i];
+
+			size_t r = rand() % str.lines;
+			str.buf[i] = str.buf[r];
+			str.buf[r] = tmp;
+		}
+	}
+
+	/* Free and print */
+	free_strings(1);
+	return 0;
+
+ERROR:
+	if (o_flag != stdout)
+		fclose(o_flag);
+
+	if (fp != NULL)
+		fclose(fp);
+
+	return 1;
+}