Hello,

I just thought it would be nice to have -lsh and -flsh options for find,
which are basically identical to -ls and -fls but output in human-readable
size format, displaying 'ls -dilsh'. My implementation patch is attached,
but it may need some tuning and testsuite.

Best,
Young
From a06510ae11b293233bd8dbe609c59d03e4728a1b Mon Sep 17 00:00:00 2001
From: Young Mo Kang <kym...@gmail.com>
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
 
+@deffn 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:
+
+@smallexample
+204744   17K -rw-r--r--   1 djm      staff       17K Nov  2  1992 ./lwall-quotes
+@end smallexample
+@end 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
 
+@deffn 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.
+@end 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

Reply via email to