On 12/13/2012 08:47 AM, Pádraig Brady wrote:
On 12/13/2012 05:34 AM, Jim Meyering wrote:
Jim Meyering wrote:
...
The awkward/somewhat redundant -n, --no-newline option
is handled in the same way as on BSD and the help text adjusted like:
- -n, --no-newline do not output the trailing newline\n\
+ -n, --no-newline do not output the separator character\n\
Good point.
Now that the long-named --no-newline is a misnomer, we might want to
provide a better long-named option (like --no-separator) and begin the
deprecation process. E.g., warn that the --no-newline option is being
deprecated, and add a FIXME to give an error in a few years.
As I reread this, I think changing/deprecating is not worth the
trouble after all.
Yes the option itself is of marginal use,
and so best just keep it around for compat
with older GNU readlink and BSD's variant.
I'll push the attached (complete with new test and doc adjustments) soon.
thanks,
Pádraig.
>From 4217f8a0fc62fa142752e8fc57cd3824ee7b7641 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <p...@draigbrady.com>
Date: Wed, 12 Dec 2012 19:54:12 +0000
Subject: [PATCH] readlink: support multiple command line arguments
This allows efficient processing of processing multiple files,
while also increasing compatibility with BSD's readlink(1).
We also add the -z, --zero option to delimit output items
with the NUL character which disambiguates output in the
presence of '\n' characters.
* src/readlink.c (usage): Add the --zero description,
and also adjust the description of --no-newline accordingly.
(main): Handle the -z option and iterate over multiple arguments.
Also as in commit v8.15-24-g9d46b25 we use fputs() and putchar()
rather than printf() for performance reasons.
* doc/coreutils.texi (readlink invocation): Document the
new --zero option, adjust the --no-newline description, and
tweak the general info to indicate multiple files are supported.
* tests/readlink/multi.sh: A new test for the new functionality.
* tests/local.mk: Reference the new test.
* NEWS: Mention the improvement.
* THANKS.in: Suggested by Aaron Davies.
---
NEWS | 2 +
THANKS.in | 1 +
doc/coreutils.texi | 14 ++++++++---
src/readlink.c | 59 +++++++++++++++++++++++------------------------
tests/local.mk | 1 +
tests/readlink/multi.sh | 34 +++++++++++++++++++++++++++
6 files changed, 77 insertions(+), 34 deletions(-)
create mode 100755 tests/readlink/multi.sh
diff --git a/NEWS b/NEWS
index 1ee2c17..7843f3c 100644
--- a/NEWS
+++ b/NEWS
@@ -61,6 +61,8 @@ GNU coreutils NEWS -*- outline -*-
** Improvements
+ readlink now supports multiple arguments.
+
stat and tail now know about CEPH. stat -f --format=%T now reports the file
system type, and tail -f uses polling for files on CEPH file systems.
diff --git a/THANKS.in b/THANKS.in
index 9009795..c2651e7 100644
--- a/THANKS.in
+++ b/THANKS.in
@@ -14,6 +14,7 @@ note to the bug-report mailing list (as seen at end of e.g., cp --help).
??? ky...@cybercomm.net
A Costa agco...@gis.net
+Aaron Davies aaron.dav...@gmail.com
Aaron Hawley ashaw...@uvm.edu
Achim Blumensath bl...@corona.oche.de
Adam Jimerson vend...@charter.net
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 5f8fad7..d393063 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -9737,20 +9737,20 @@ Set the default SELinux security context to be used for created files.
@item Readlink mode
-@command{readlink} outputs the value of the given symbolic link.
+@command{readlink} outputs the value of the given symbolic links.
If @command{readlink} is invoked with an argument other than the name
of a symbolic link, it produces no output and exits with a nonzero exit code.
@item Canonicalize mode
-@command{readlink} outputs the absolute name of the given file which contains
+@command{readlink} outputs the absolute name of the given files which contain
no @file{.}, @file{..} components nor any repeated separators
(@file{/}) or symbolic links.
@end table
@example
-readlink [@var{option}] @var{file}
+readlink [@var{option}]@dots{} @var{file}@dots{}
@end example
By default, @command{readlink} operates in readlink mode.
@@ -9789,7 +9789,7 @@ as a directory.
@itemx --no-newline
@opindex -n
@opindex --no-newline
-Do not output the trailing newline.
+Do not print the output delimiter.
@item -s
@itemx -q
@@ -9807,6 +9807,12 @@ Suppress most error messages.
@opindex --verbose
Report error messages.
+@item -z
+@itemx --zero
+@opindex -z
+@opindex --zero
+Separate output items with @sc{nul} characters.
+
@end table
The @command{readlink} utility first appeared in OpenBSD 2.1.
diff --git a/src/readlink.c b/src/readlink.c
index e025bf9..de8211f 100644
--- a/src/readlink.c
+++ b/src/readlink.c
@@ -25,7 +25,6 @@
#include "canonicalize.h"
#include "error.h"
#include "areadlink.h"
-#include "quote.h"
/* The official name of this program (e.g., no 'g' prefix). */
#define PROGRAM_NAME "readlink"
@@ -47,6 +46,7 @@ static struct option const longopts[] =
{"quiet", no_argument, NULL, 'q'},
{"silent", no_argument, NULL, 's'},
{"verbose", no_argument, NULL, 'v'},
+ {"zero", no_argument, NULL, 'z'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
@@ -59,7 +59,7 @@ usage (int status)
emit_try_help ();
else
{
- printf (_("Usage: %s [OPTION]... FILE\n"), program_name);
+ printf (_("Usage: %s [OPTION]... FILE...\n"), program_name);
fputs (_("Print value of a symbolic link or canonical file name\n\n"),
stdout);
fputs (_("\
@@ -77,10 +77,11 @@ usage (int status)
every component of the given name recursively,\
\n\
without requirements on components existence\n\
- -n, --no-newline do not output the trailing newline\n\
+ -n, --no-newline do not output a delimiter after each item\n\
-q, --quiet,\n\
-s, --silent suppress most error messages\n\
-v, --verbose report error messages\n\
+ -z, --zero separate output with NUL rather than newline\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
@@ -94,14 +95,9 @@ main (int argc, char **argv)
{
/* If not -1, use this method to canonicalize. */
int can_mode = -1;
-
- /* File name to canonicalize. */
- const char *fname;
-
- /* Result of canonicalize. */
- char *value;
-
+ int status = EXIT_SUCCESS;
int optc;
+ bool use_nuls = false;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
@@ -111,7 +107,7 @@ main (int argc, char **argv)
atexit (close_stdout);
- while ((optc = getopt_long (argc, argv, "efmnqsv", longopts, NULL)) != -1)
+ while ((optc = getopt_long (argc, argv, "efmnqsvz", longopts, NULL)) != -1)
{
switch (optc)
{
@@ -134,6 +130,9 @@ main (int argc, char **argv)
case 'v':
verbose = true;
break;
+ case 'z':
+ use_nuls = true;
+ break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
@@ -147,26 +146,26 @@ main (int argc, char **argv)
usage (EXIT_FAILURE);
}
- fname = argv[optind++];
-
- if (optind < argc)
- {
- error (0, 0, _("extra operand %s"), quote (argv[optind]));
- usage (EXIT_FAILURE);
- }
-
- value = (can_mode != -1
- ? canonicalize_filename_mode (fname, can_mode)
- : areadlink_with_size (fname, 63));
- if (value)
+ for (; optind < argc; ++optind)
{
- printf ("%s%s", value, (no_newline ? "" : "\n"));
- free (value);
- return EXIT_SUCCESS;
+ const char *fname = argv[optind];
+ char *value = (can_mode != -1
+ ? canonicalize_filename_mode (fname, can_mode)
+ : areadlink_with_size (fname, 63));
+ if (value)
+ {
+ fputs (value, stdout);
+ if (! no_newline)
+ putchar (use_nuls ? '\0' : '\n');
+ free (value);
+ }
+ else
+ {
+ status = EXIT_FAILURE;
+ if (verbose)
+ error (0, errno, "%s", fname);
+ }
}
- if (verbose)
- error (EXIT_FAILURE, errno, "%s", fname);
-
- return EXIT_FAILURE;
+ return status;
}
diff --git a/tests/local.mk b/tests/local.mk
index 5eeddd5..efdd896 100644
--- a/tests/local.mk
+++ b/tests/local.mk
@@ -602,6 +602,7 @@ all_tests = \
tests/readlink/can-e.sh \
tests/readlink/can-f.sh \
tests/readlink/can-m.sh \
+ tests/readlink/multi.sh \
tests/readlink/rl-1.sh \
tests/rmdir/fail-perm.sh \
tests/rmdir/ignore.sh \
diff --git a/tests/readlink/multi.sh b/tests/readlink/multi.sh
new file mode 100755
index 0000000..b28a705
--- /dev/null
+++ b/tests/readlink/multi.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+# test multiple argument handling.
+
+# Copyright (C) 2012 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ readlink
+
+touch regfile || framework_failure_
+ln -s regfile link1 || framework_failure_
+
+readlink link1 link1 || fail=1
+readlink link1 link2 && fail=1
+readlink link1 link2 link1 && fail=1
+readlink -m link1 link2 || fail=1
+
+printf "/1\0/1\0" > exp
+readlink -m --zero /1 /1 > out
+compare exp out || fail=1
+
+Exit $fail
--
1.7.6.4