From a06510ae11b293233bd8dbe609c59d03e4728a1b Mon Sep 17 00:00:00 2001 From: Young Mo Kang Date: Sun, 1 May 2016 22:24:55 +0900 Subject: [PATCH] find: support list in human-readable format * lib/listfile.h (enum ls_option): Add option for list_file print format (list_file) Edit prototype accordingly (see below) * lib/listfile.c (list_file): Add ls_option as a parameter. Print block size and file size in format as specified. * find/defs.h (pred_flsh): Add prototype (pred_lsh): Likewise * find/parser.c (parse_flsh): Add prototype and function (parse_lsh): Likewise (parse_table): Add the two entries above * find/pred.c (pred_table): Add pred_lsh entry (pred_fls): Call list_file with ls_dils option (pred_flsh): Call list_file with ls_dilsh option * find/tree.c (costlookup): Add pred_lsh and pred_flsh entries * find/find.1: Document the new feature * doc/find.texi: Likewise * NEWS: Likewise --- NEWS | 3 +++ doc/find.texi | 16 ++++++++++++++++ find/defs.h | 2 ++ find/find.1 | 13 +++++++++++++ find/parser.c | 16 ++++++++++++++++ find/pred.c | 26 +++++++++++++++++++++++--- find/tree.c | 2 ++ lib/listfile.c | 45 +++++++++++++++++++++++++++++++++++---------- lib/listfile.h | 13 ++++++++++++- 9 files changed, 122 insertions(+), 14 deletions(-) diff --git a/NEWS b/NEWS index 59f6cb9..c2f9d95 100644 --- a/NEWS +++ b/NEWS @@ -32,6 +32,9 @@ options separated by comma ','. For example, to search for symbolic links and directories simply provide the shorter '-type l,d' instead of the - yet more portable - '( -type l -o -type d )'. +find now accepts -lsh and -flsh options, which are similar to -ls and +-fls options but print in human-readable format as in 'ls -dilsh'. + ** Bug Fixes #46784: frcode drops last char if no final newline diff --git a/doc/find.texi b/doc/find.texi index 93c67c3..0979298 100644 --- a/doc/find.texi +++ b/doc/find.texi @@ -1678,12 +1678,28 @@ the treatment of unprintable characters is harmonised for @samp{-ls}, @end enumerate @end deffn address@hidden Action -lsh +True; like @samp{-ls} but list the current file in the @samp{ls -dilsh} +format (i.e., print block size and file's size in human readable format). +The output looks like this: + address@hidden +204744 17K -rw-r--r-- 1 djm staff 17K Nov 2 1992 ./lwall-quotes address@hidden smallexample address@hidden deffn + @deffn Action -fls file True; like @samp{-ls} but write to @var{file} like @samp{-fprint} (@pxref{Print File Name}). The named output file is always created, even if no output is sent to it. @end deffn address@hidden Action -flsh file +True; like @samp{-lsh} but write to @var{file} like @samp{-fprint} +(@pxref{Print File Name}). The named output file is always created, +even if no output is sent to it. address@hidden deffn + @deffn Action -printf format True; print @var{format} on the standard output, interpreting @samp{\} escapes and @samp{%} directives (more details in the following diff --git a/find/defs.h b/find/defs.h index 52e522f..7e73eaa 100644 --- a/find/defs.h +++ b/find/defs.h @@ -430,6 +430,7 @@ PREDICATEFUNCTION pred_execdir; PREDICATEFUNCTION pred_executable; PREDICATEFUNCTION pred_false; PREDICATEFUNCTION pred_fls; +PREDICATEFUNCTION pred_flsh; PREDICATEFUNCTION pred_fprint; PREDICATEFUNCTION pred_fprint0; PREDICATEFUNCTION pred_fprintf; @@ -443,6 +444,7 @@ PREDICATEFUNCTION pred_ipath; PREDICATEFUNCTION pred_links; PREDICATEFUNCTION pred_lname; PREDICATEFUNCTION pred_ls; +PREDICATEFUNCTION pred_lsh; PREDICATEFUNCTION pred_mmin; PREDICATEFUNCTION pred_mtime; PREDICATEFUNCTION pred_name; diff --git a/find/find.1 b/find/find.1 index 8958085..87b9183 100644 --- a/find/find.1 +++ b/find/find.1 @@ -1149,6 +1149,14 @@ See the .B UNUSUAL FILENAMES section for information about how unusual characters in filenames are handled. +.IP "\-flsh \fIfile\fR" +True; like +.B \-lsh +but write to \fIfile\fR like +.BR \-fprint . +The output file is always created, even if the predicate is never +matched. + .IP "\-fprint \fIfile\fR" True; print the full file name into file \fIfile\fR. If \fIfile\fR does not exist when \fBfind\fR is run, it is created; if it does @@ -1190,6 +1198,11 @@ See the .B UNUSUAL FILENAMES section for information about how unusual characters in filenames are handled. +.IP \-lsh +True; list current file in +.B ls \-dilsh +format on standard output. + .IP "\-ok \fIcommand\fR ;" Like .B \-exec diff --git a/find/parser.c b/find/parser.c index dfe0523..e15819d 100644 --- a/find/parser.c +++ b/find/parser.c @@ -100,6 +100,7 @@ static bool parse_exec (const struct parser_table*, char *argv[], int * static bool parse_execdir (const struct parser_table*, char *argv[], int *arg_ptr); static bool parse_false (const struct parser_table*, char *argv[], int *arg_ptr); static bool parse_fls (const struct parser_table*, char *argv[], int *arg_ptr); +static bool parse_flsh (const struct parser_table*, char *argv[], int *arg_ptr); static bool parse_fprintf (const struct parser_table*, char *argv[], int *arg_ptr); static bool parse_follow (const struct parser_table*, char *argv[], int *arg_ptr); static bool parse_fprint (const struct parser_table*, char *argv[], int *arg_ptr); @@ -116,6 +117,7 @@ static bool parse_iwholename (const struct parser_table*, char *argv[], int * static bool parse_links (const struct parser_table*, char *argv[], int *arg_ptr); static bool parse_lname (const struct parser_table*, char *argv[], int *arg_ptr); static bool parse_ls (const struct parser_table*, char *argv[], int *arg_ptr); +static bool parse_lsh (const struct parser_table*, char *argv[], int *arg_ptr); static bool parse_maxdepth (const struct parser_table*, char *argv[], int *arg_ptr); static bool parse_mindepth (const struct parser_table*, char *argv[], int *arg_ptr); static bool parse_mmin (const struct parser_table*, char *argv[], int *arg_ptr); @@ -251,6 +253,7 @@ static struct parser_table const parse_table[] = {ARG_TEST, "executable", parse_accesscheck, pred_executable}, /* GNU, 4.3.0+ */ PARSE_ACTION ("execdir", execdir), /* *BSD, GNU */ PARSE_ACTION ("fls", fls), /* GNU */ + PARSE_ACTION ("flsh", flsh), /* GNU */ PARSE_POSOPT ("follow", follow), /* GNU, Unix */ PARSE_ACTION ("fprint", fprint), /* GNU */ PARSE_ACTION ("fprint0", fprint0), /* GNU */ @@ -268,6 +271,7 @@ static struct parser_table const parse_table[] = PARSE_TEST ("links", links), /* POSIX */ PARSE_TEST ("lname", lname), /* GNU */ PARSE_ACTION ("ls", ls), /* GNU, Unix */ + PARSE_ACTION ("lsh", lsh), /* GNU */ PARSE_OPTION ("maxdepth", maxdepth), /* GNU */ PARSE_OPTION ("mindepth", mindepth), /* GNU */ PARSE_TEST ("mmin", mmin), /* GNU */ @@ -1002,6 +1006,12 @@ parse_fls (const struct parser_table* entry, char **argv, int *arg_ptr) } static bool +parse_flsh (const struct parser_table* entry, char **argv, int *arg_ptr) +{ + return parse_fls (entry, argv, arg_ptr); +} + +static bool parse_follow (const struct parser_table* entry, char **argv, int *arg_ptr) { set_follow_state (SYMLINK_ALWAYS_DEREF); @@ -1407,6 +1417,12 @@ parse_ls (const struct parser_table* entry, char **argv, int *arg_ptr) } static bool +parse_lsh (const struct parser_table* entry, char **argv, int *arg_ptr) +{ + return parse_ls (entry, argv, arg_ptr); +} + +static bool insert_depthspec (const struct parser_table* entry, char **argv, int *arg_ptr, int *limitptr) { diff --git a/find/pred.c b/find/pred.c index f7e9b59..51e91ba 100644 --- a/find/pred.c +++ b/find/pred.c @@ -106,6 +106,7 @@ struct pred_assoc pred_table[] = {pred_links, "links "}, {pred_lname, "lname "}, {pred_ls, "ls "}, + {pred_lsh, "lsh "}, {pred_mmin, "mmin "}, {pred_mtime, "mtime "}, {pred_name, "name "}, @@ -425,17 +426,30 @@ pred_false (const char *pathname, struct stat *stat_buf, struct predicate *pred_ (void) &stat_buf; (void) &pred_ptr; - return (false); } + bool pred_fls (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr) { FILE * stream = pred_ptr->args.printf_vec.stream; list_file (pathname, state.cwd_dir_fd, state.rel_pathname, stat_buf, - options.start_time.tv_sec, - options.output_block_size, + options.start_time.tv_sec, + options.output_block_size, + ls_dils, + pred_ptr->literal_control_chars, stream); + return true; +} + +bool +pred_flsh (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr) +{ + FILE * stream = pred_ptr->args.printf_vec.stream; + list_file (pathname, state.cwd_dir_fd, state.rel_pathname, stat_buf, + options.start_time.tv_sec, + options.output_block_size, + ls_dilsh, pred_ptr->literal_control_chars, stream); return true; } @@ -647,6 +661,12 @@ pred_ls (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr } bool +pred_lsh (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr) +{ + return pred_flsh (pathname, stat_buf, pred_ptr); +} + +bool pred_mmin (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr) { (void) &pathname; diff --git a/find/tree.c b/find/tree.c index 8a413f8..1e7b4e2 100644 --- a/find/tree.c +++ b/find/tree.c @@ -966,7 +966,9 @@ static struct pred_cost_lookup costlookup[] = { pred_links , NeedsStatInfo }, { pred_lname , NeedsLinkName }, { pred_ls , NeedsStatInfo }, + { pred_lsh , NeedsStatInfo }, { pred_fls , NeedsStatInfo }, + { pred_flsh , NeedsStatInfo }, { pred_mmin , NeedsStatInfo }, { pred_mtime , NeedsStatInfo }, { pred_name , NeedsNothing }, diff --git a/lib/listfile.c b/lib/listfile.c index cc76e0a..1dd98d3 100644 --- a/lib/listfile.c +++ b/lib/listfile.c @@ -115,6 +115,7 @@ list_file (const char *name, const struct stat *statp, time_t current_time, int output_block_size, + int ls_option, int literal_control_chars, FILE *stream) { @@ -154,11 +155,23 @@ list_file (const char *name, output_good = false; failed_at = 150; } - chars_out = fprintf (stream, "%*s", - block_size_width, - human_readable ((uintmax_t) ST_NBLOCKS (*statp), hbuf, - human_ceiling, - ST_NBLOCKSIZE, output_block_size)); + switch (ls_option) + { + case ls_dils: + chars_out = fprintf (stream, "%*s", + block_size_width, + human_readable ((uintmax_t) ST_NBLOCKS (*statp), hbuf, + human_ceiling, + ST_NBLOCKSIZE, output_block_size)); + break; + case ls_dilsh: + chars_out = fprintf (stream, "%*s", + block_size_width, + human_readable ((uintmax_t) ST_NBLOCKS (*statp), hbuf, + human_autoscale | human_SI | human_base_1024, + ST_NBLOCKSIZE, 1)); + break; + } if (chars_out < 0) { output_good = false; @@ -315,11 +328,23 @@ list_file (const char *name, else { const int blocksize = output_block_size < 0 ? output_block_size : 1; - chars_out = fprintf (stream, "%*s", - file_size_width, - human_readable ((uintmax_t) statp->st_size, hbuf, - human_ceiling, - 1, blocksize)); + switch (ls_option) + { + case ls_dils: + chars_out = fprintf (stream, "%*s", + file_size_width, + human_readable ((uintmax_t) statp->st_size, hbuf, + human_ceiling, + 1, blocksize)); + break; + case ls_dilsh: + chars_out = fprintf (stream, "%*s", + file_size_width, + human_readable ((uintmax_t) statp->st_size, hbuf, + human_autoscale | human_SI | human_base_1024, + 1, blocksize)); + break; + } if (chars_out < 0) { output_good = false; diff --git a/lib/listfile.h b/lib/listfile.h index 9514c58..543b6fb 100644 --- a/lib/listfile.h +++ b/lib/listfile.h @@ -19,5 +19,16 @@ #if !defined LISTFILE_H # define LISTFILE_H -void list_file (const char *name, int dir_fd, const char *relname, const struct stat *statp, time_t current_time, int output_block_size, int literal_control_chars, FILE *stream); + +/* Options for list_file. */ +enum +{ + /* -ls and -fls */ + ls_dils, + + /* -lsh and -flsh */ + ls_dilsh +}; + +void list_file (const char *name, int dir_fd, const char *relname, const struct stat *statp, time_t current_time, int output_block_size, int ls_option, int literal_control_chars, FILE *stream); #endif -- 2.7.4