diff --git a/doc/ncdu.pod b/doc/ncdu.pod index 2946c3df76f20c04d6db5401dcd2775135b534e3..99a75777717ab3e8b437c16cb1305dd85170384f 100644 --- a/doc/ncdu.pod +++ b/doc/ncdu.pod @@ -67,6 +67,9 @@ when importing (to read this extra information in memory). This flag has no effect when importing a file that has been exported without the extended information. +This enables viewing and sorting by the latest child mtime, or modified time, +using 'm' and 'M', respectively. + =back =head2 Interface options @@ -208,6 +211,11 @@ Order by number of items (press again for descending order) Toggle between showing disk usage and showing apparent size. +=item M + +Order by latest child mtime, or modified time. (press again for descending order) +Requires the -e flag. + =item d Delete the selected file or directory. An error message will be shown when the @@ -228,6 +236,10 @@ the current directory. Toggle display of child item counts. +=item m + +Toggle display of latest child mtime, or modified time. Requies the -e flag. + =item e Show/hide 'hidden' or 'excluded' files and directories. Please note that even diff --git a/src/browser.c b/src/browser.c index 97132bad040350fd5ad5a478635927caa361a7b4..7cd0ac58643f474e138e5a534c3851cd2cd72c50 100644 --- a/src/browser.c +++ b/src/browser.c @@ -31,7 +31,7 @@ #include <time.h> -static int graph = 1, show_as = 0, info_show = 0, info_page = 0, info_start = 0, show_items = 0; +static int graph = 1, show_as = 0, info_show = 0, info_page = 0, info_start = 0, show_items = 0, show_mtime = 0; static char *message = NULL; @@ -196,6 +196,30 @@ static void browse_draw_items(struct dir *n, int *x) { } +static void browse_draw_mtime(struct dir *n, int *x) { + enum ui_coltype c = n->flags & FF_BSEL ? UIC_SEL : UIC_DEFAULT; + char mbuf[26]; + struct dir_ext *e; + time_t t; + + if (n->flags & FF_EXT) { + e = dir_ext_ptr(n); + } else if (!strcmp(n->name, "..") && (n->parent->flags & FF_EXT)) { + e = dir_ext_ptr(n->parent); + } else { + snprintf(mbuf, sizeof(mbuf), "no mtime"); + goto no_mtime; + } + t = (time_t)e->mtime; + + strftime(mbuf, sizeof(mbuf), "%Y-%m-%d %H:%M:%S %z", localtime(&t)); + uic_set(c == UIC_SEL ? UIC_NUM_SEL : UIC_NUM); +no_mtime: + printw("%26s", mbuf); + *x += 27; +} + + static void browse_draw_item(struct dir *n, int row) { int x = 0; @@ -218,6 +242,11 @@ static void browse_draw_item(struct dir *n, int row) { browse_draw_items(n, &x); move(row, x); + if (extended_info && show_mtime) { + browse_draw_mtime(n, &x); + move(row, x); + } + if(n->flags & FF_DIR) c = c == UIC_SEL ? UIC_DIR_SEL : UIC_DIR; addchc(c, n->flags & FF_DIR ? '/' : ' '); @@ -409,6 +438,12 @@ int browse_key(int ch) { dirlist_set_sort(DL_COL_ITEMS, dirlist_sort_col == DL_COL_ITEMS ? !dirlist_sort_desc : 1, DL_NOCHANGE); info_show = 0; break; + case 'M': + if (extended_info) { + dirlist_set_sort(DL_COL_MTIME, dirlist_sort_col == DL_COL_MTIME ? !dirlist_sort_desc : 1, DL_NOCHANGE); + info_show = 0; + } + break; case 'e': dirlist_set_hidden(!dirlist_hidden); info_show = 0; @@ -474,6 +509,10 @@ int browse_key(int ch) { case 'c': show_items = !show_items; break; + case 'm': + if (extended_info) + show_mtime = !show_mtime; + break; case 'i': info_show = !info_show; break; diff --git a/src/dir_mem.c b/src/dir_mem.c index 5007980925bbd1213d639c8a84f004e2070412d6..dc155860c5608513a98beabc9e2bc3b43baa8c9d 100644 --- a/src/dir_mem.c +++ b/src/dir_mem.c @@ -144,10 +144,13 @@ static int item(struct dir *dir, const char *name, struct dir_ext *ext) { * possible hard link, because hlnk_check() will take care of it in that * case. */ if(item->flags & FF_HLNKC) { - addparentstats(item->parent, 0, 0, 1); + addparentstats(item->parent, 0, 0, 0, 1); hlink_check(item); - } else - addparentstats(item->parent, item->size, item->asize, 1); + } else if(item->flags & FF_EXT) { + addparentstats(item->parent, item->size, item->asize, dir_ext_ptr(item)->mtime, 1); + } else { + addparentstats(item->parent, item->size, item->asize, 0, 1); + } /* propagate ERR and SERR back up to the root */ if(item->flags & FF_SERR || item->flags & FF_ERR) diff --git a/src/dirlist.c b/src/dirlist.c index da51a98e4cfbc9fc25f2d7ced1a3c0ebec9b5acb..63a4cac52a22deacada696a52f3fd70ce9b177d2 100644 --- a/src/dirlist.c +++ b/src/dirlist.c @@ -50,6 +50,14 @@ static struct dir *parent_alloc, *head, *head_real, *selected, *top = NULL; )) +static inline int cmp_mtime(struct dir *x, struct dir*y) { + int64_t x_mtime = 0, y_mtime = 0; + if (x->flags & FF_EXT) + x_mtime = dir_ext_ptr(x)->mtime; + if (y->flags & FF_EXT) + y_mtime = dir_ext_ptr(y)->mtime; + return (x_mtime > y_mtime ? 1 : (x_mtime == y_mtime ? 0 : -1)); +} static int dirlist_cmp(struct dir *x, struct dir *y) { int r; @@ -80,7 +88,8 @@ static int dirlist_cmp(struct dir *x, struct dir *y) { r = dirlist_sort_col == DL_COL_NAME ? CMP_NAME : dirlist_sort_col == DL_COL_SIZE ? CMP_SIZE : dirlist_sort_col == DL_COL_ASIZE ? CMP_ASIZE : - CMP_ITEMS; + dirlist_sort_col == DL_COL_ITEMS ? CMP_ITEMS : + cmp_mtime(x, y); /* try 2 */ if(!r) r = dirlist_sort_col == DL_COL_SIZE ? CMP_ASIZE : CMP_SIZE; diff --git a/src/dirlist.h b/src/dirlist.h index 6e19e4fad9c2599fd7513f8e2f0973990fc2f053..5437e4bbea502aaf5f966856b514f7dfc8bc1de8 100644 --- a/src/dirlist.h +++ b/src/dirlist.h @@ -37,6 +37,7 @@ #define DL_COL_SIZE 1 #define DL_COL_ASIZE 2 #define DL_COL_ITEMS 3 +#define DL_COL_MTIME 4 void dirlist_open(struct dir *); diff --git a/src/help.c b/src/help.c index 1c46b0f381712aca2aa3eb2309e58749364a3c8a..caba9b3e0289a30a84759fbc4ba40afada526761 100644 --- a/src/help.c +++ b/src/help.c @@ -32,7 +32,7 @@ int page, start; -#define KEYS 17 +#define KEYS 19 char *keys[KEYS*2] = { /*|----key----| |----------------description----------------|*/ "up, k", "Move cursor up", @@ -42,11 +42,13 @@ char *keys[KEYS*2] = { "n", "Sort by name (ascending/descending)", "s", "Sort by size (ascending/descending)", "C", "Sort by items (ascending/descending)", + "M", "Sort by mtime (-e flag)", "d", "Delete selected file or directory", "t", "Toggle dirs before files when sorting", "g", "Show percentage and/or graph", "a", "Toggle between apparent size and disk usage", "c", "Toggle display of child item counts", + "m", "Toggle display of latest mtime (-e flag)", "e", "Show/hide hidden or excluded files", "i", "Show information about selected item", "r", "Recalculate the current directory", diff --git a/src/util.c b/src/util.c index 5f3dbd38806fc0fd4f775a3d68f4426fa900f902..45660bfbd2377fc9f409c7f27a25813a8c5ba975 100644 --- a/src/util.c +++ b/src/util.c @@ -344,8 +344,11 @@ void freedir(struct dir *dr) { freedir_hlnk(dr); /* update sizes of parent directories if this isn't a hard link. - * If this is a hard link, freedir_hlnk() would have done so already */ - addparentstats(dr->parent, dr->flags & FF_HLNKC ? 0 : -dr->size, dr->flags & FF_HLNKC ? 0 : -dr->asize, -(dr->items+1)); + * If this is a hard link, freedir_hlnk() would have done so already + * + * mtime is 0 here because recalculating the maximum at every parent + * dir is expensive, but might be good feature to add later if desired */ + addparentstats(dr->parent, dr->flags & FF_HLNKC ? 0 : -dr->size, dr->flags & FF_HLNKC ? 0 : -dr->asize, 0, -(dr->items+1)); free(dr); } @@ -397,11 +400,16 @@ struct dir *getroot(struct dir *d) { } -void addparentstats(struct dir *d, int64_t size, int64_t asize, int items) { +void addparentstats(struct dir *d, int64_t size, int64_t asize, uint64_t mtime, int items) { + struct dir_ext *e; while(d) { d->size = adds64(d->size, size); d->asize = adds64(d->asize, asize); d->items += items; + if (d->flags & FF_EXT) { + e = dir_ext_ptr(d); + e->mtime = (e->mtime > mtime) ? e->mtime : mtime; + } d = d->parent; } } diff --git a/src/util.h b/src/util.h index 0af8e77a86375873e7a7842e0a1fed4007ac3a9c..a1b9781a4a8adcfcc3dadbf495490c9bd31f40fa 100644 --- a/src/util.h +++ b/src/util.h @@ -163,7 +163,7 @@ struct dir *getroot(struct dir *); : (a)+(b) < 0 ? 0 : (a)+(b)) /* Adds a value to the size, asize and items fields of *d and its parents */ -void addparentstats(struct dir *, int64_t, int64_t, int); +void addparentstats(struct dir *, int64_t, int64_t, uint64_t, int); /* A simple stack implemented in macros */