Index: uspace/app/bdsh/cmds/modules/ls/ls.c
===================================================================
--- uspace/app/bdsh/cmds/modules/ls/ls.c	(revision 46288eef683d4b03bcbb084da70081298922bd22)
+++ uspace/app/bdsh/cmds/modules/ls/ls.c	(revision c8cf261a450bf22fa6cc6e9872a1f07f9e7dccda)
@@ -42,4 +42,5 @@
 #include <vfs/vfs.h>
 #include <str.h>
+#include <cap.h>
 
 #include "ls.h"
@@ -58,4 +59,6 @@
 	{ "unsort", no_argument, 0, 'u' },
 	{ "recursive", no_argument, 0, 'r' },
+	{ "exact-size", no_argument, 0, 'e' },
+	{ "single-column", no_argument, 0, '1' },
 	{ 0, 0, 0, 0 }
 };
@@ -63,6 +66,8 @@
 /* Prototypes for the ls command, excluding entry points. */
 static unsigned int ls_start(ls_job_t *);
-static void ls_print(struct dir_elem_t *);
-static int ls_cmp(const void *, const void *);
+static errno_t ls_print(struct dir_elem_t *);
+static errno_t ls_print_single_column(struct dir_elem_t *);
+static int ls_cmp_type_name(const void *, const void *);
+static int ls_cmp_name(const void *, const void *);
 static signed int ls_scan_dir(const char *, DIR *, struct dir_elem_t **);
 static unsigned int ls_recursive(const char *, DIR *);
@@ -74,4 +79,7 @@
 	ls->sort = 1;
 
+	ls->exact_size = false;
+	ls->single_column = false;
+	ls->printer = ls_print;
 	return 1;
 }
@@ -88,12 +96,51 @@
  * @param de		Directory element.
  */
-static void ls_print(struct dir_elem_t *de)
-{
-	if (de->s.is_file)
-		printf("%-40s\t%llu\n", de->name, (long long) de->s.size);
-	else if (de->s.is_directory)
-		printf("%-40s\t<dir>\n", de->name);
+static errno_t ls_print(struct dir_elem_t *de)
+{
+	int width = 13;
+
+	if (de->s.is_file) {
+		if (ls.exact_size) {
+			printf("%-40s\t%*llu\n", de->name, width, (long long) de->s.size);
+			return EOK;
+		}
+
+		cap_spec_t cap;
+		cap_from_blocks(de->s.size, 1, &cap);
+		cap_simplify(&cap);
+
+		char *rptr;
+		errno_t rc = cap_format(&cap, &rptr);
+		if (rc != EOK) {
+			return rc;
+		}
+
+		char *sep = str_rchr(rptr, ' ');
+		if (sep == NULL) {
+			free(rptr);
+			return ENOENT;
+		}
+
+		*sep = '\0';
+
+		printf("%-40s\t%*s %2s\n", de->name, width - 3, rptr, sep + 1);
+		free(rptr);
+	} else if (de->s.is_directory)
+		printf("%-40s\t%*s\n", de->name, width, "<dir>");
 	else
 		printf("%-40s\n", de->name);
+
+	return EOK;
+}
+
+static errno_t ls_print_single_column(struct dir_elem_t *de)
+{
+	if (de->s.is_file) {
+		printf("%s\n", de->name);
+	} else {
+		printf("%s/\n", de->name);
+	}
+
+	return EOK;
 }
 
@@ -109,5 +156,5 @@
  * @return		-1 if a < b, 1 otherwise.
  */
-static int ls_cmp(const void *a, const void *b)
+static int ls_cmp_type_name(const void *a, const void *b)
 {
 	struct dir_elem_t const *da = a;
@@ -120,4 +167,18 @@
 	else
 		return 1;
+}
+
+/** Compare directories/files per name
+ *
+ * This comparision ignores the type of
+ * the node. Sorted will strictly by name.
+ *
+ */
+static int ls_cmp_name(const void *a, const void *b)
+{
+	struct dir_elem_t const *da = a;
+	struct dir_elem_t const *db = b;
+
+	return str_cmp(da->name, db->name);
 }
 
@@ -192,9 +253,16 @@
 	}
 
-	if (ls.sort)
-		qsort(&tosort[0], nbdirs, sizeof(struct dir_elem_t), ls_cmp);
-
-	for (i = 0; i < nbdirs; i++)
-		ls_print(&tosort[i]);
+	if (ls.sort) {
+		int (*compar)(const void *, const void *);
+		compar = ls.single_column ? ls_cmp_name : ls_cmp_type_name;
+		qsort(&tosort[0], nbdirs, sizeof(struct dir_elem_t), compar);
+	}
+
+	for (i = 0; i < nbdirs; i++) {
+		if (ls.printer(&tosort[i]) != EOK) {
+			cli_error(CL_ENOMEM, "%s: Out of memory", cmdname);
+			goto out;
+		}
+	}
 
 	/* Populate the directory list. */
@@ -333,7 +401,9 @@
 		    "If not path is given, the current working directory is used.\n"
 		    "Options:\n"
-		    "  -h, --help       A short option summary\n"
-		    "  -u, --unsort     Do not sort directory entries\n"
-		    "  -r, --recursive  List subdirectories recursively\n",
+		    "  -h, --help            A short option summary\n"
+		    "  -u, --unsort          Do not sort directory entries\n"
+		    "  -r, --recursive       List subdirectories recursively\n"
+		    "  -e, --exact-size      File sizes will be unformatted (raw bytes count)\n"
+		    "  -1, --single-column   Only the names will be returned\n",
 		    cmdname);
 	}
@@ -364,5 +434,5 @@
 
 	while (c != -1) {
-		c = getopt_long(argc, argv, "hur", long_options, &opt_ind);
+		c = getopt_long(argc, argv, "hure1", long_options, &opt_ind);
 		switch (c) {
 		case 'h':
@@ -375,4 +445,11 @@
 			ls.recursive = 1;
 			break;
+		case 'e':
+			ls.exact_size = true;
+			break;
+		case '1':
+			ls.single_column = true;
+			ls.printer = ls_print_single_column;
+			break;
 		}
 	}
@@ -400,5 +477,8 @@
 	switch (scope) {
 	case LS_FILE:
-		ls_print(&de);
+		if (ls.printer(&de) != EOK) {
+			cli_error(CL_ENOMEM, "%s: Out of memory", cmdname);
+			return CMD_FAILURE;
+		}
 		break;
 	case LS_DIR:
Index: uspace/app/bdsh/cmds/modules/ls/ls.h
===================================================================
--- uspace/app/bdsh/cmds/modules/ls/ls.h	(revision 46288eef683d4b03bcbb084da70081298922bd22)
+++ uspace/app/bdsh/cmds/modules/ls/ls.h	(revision c8cf261a450bf22fa6cc6e9872a1f07f9e7dccda)
@@ -8,11 +8,4 @@
 #define LS_FILE  1
 #define LS_DIR   2
-
-typedef struct {
-	/* Options set at runtime. */
-	unsigned int recursive;
-	unsigned int sort;
-
-} ls_job_t;
 
 /** Structure to represent a directory entry.
@@ -26,3 +19,14 @@
 };
 
+typedef struct {
+	/* Options set at runtime. */
+	unsigned int recursive;
+	unsigned int sort;
+
+	bool single_column;
+	bool exact_size;
+
+	errno_t (*printer)(struct dir_elem_t *);
+} ls_job_t;
+
 #endif
