Gibt es einen Grund, warum ls keine Option --zero oder -0 hat?

37

Diese Frage wurde von Fragen über Aufforderung ls" -1Option und die wiederkehrende Tendenz der Menschen , Fragen und Antworten zu stellen, die die Ausgabe beinhaltet die Verarbeitung ls.

Diese Wiederverwendung der Ausgabe lserscheint verständlich, z. B .: Wenn Sie wissen, wie eine Liste von Dateien sortiert wird, lsmöchten Sie die Ausgabe möglicherweise auf diese Weise als Eingabe für etwas anderes verwenden.

Wenn diese Fragen und Antworten keinen Verweis auf die erstellte Dateinamenliste enthalten, die aus sich gut verhaltenden Dateinamen besteht (keine Sonderzeichen wie Leerzeichen und Zeilenumbrüche), werden sie häufig von jemandem kommentiert, der auf die Gefahr hinweist, dass die Befehlssequenz dort nicht funktioniert sind Dateien mit Zeilenumbrüchen, Leerzeichen usw.

find, sortund andere Hilfsprogramme lösen das Problem der Übermittlung "schwieriger" Dateinamen, xargsindem z. B. eine Option zum Trennen der Dateinamen mit dem NUL-Zeichen / Byte verwendet wird, das kein gültiges Zeichen im Dateinamen ist (das einzige zusätzlich zu /?) Unix / Linux-Dateisysteme.

Ich habe in der Manpage nach lsund in der Ausgabe nach ls --help(die mehr Optionen enthält) gesucht und konnte nicht feststellen, dass ls(von coreutils) eine Option zur Angabe einer durch NUL getrennten Ausgabe enthält. Es macht einen haben -1Option , die als interpretiert werden kann „Ausgabedateinamen durch Newline getrennt“ )

F : Gibt es einen technischen oder philosophischen Grund, warum lses keine Option --zerooder gibt -0, die "Dateinamen durch NUL getrennt ausgeben" würde?

Wenn Sie etwas tun, das nur die Dateinamen ausgibt (und nicht zB verwendet -l), könnte dies Sinn machen:

ls -rt -0 | xargs -r0 

Mir könnte etwas fehlen, warum dies nicht funktionieren würde, oder es gibt eine Alternative für dieses Beispiel, die ich übersehen habe und die nicht viel komplizierter und / oder undurchsichtiger ist .


Nachtrag:

Doing ls -lrt -0wahrscheinlich machen nicht viel Sinn, aber in der gleichen Art und Weise , die find . -ls -print0nicht der Fall ist, so dass kein Grund zu keinen bieten -0/ -z/ --zeroOption.

Timo
quelle
Es liegt auf der Hand, zu schreiben und den Betreuer von GNU coreutils zu fragen, was er von einer solchen Option hält.
Faheem Mitha
1
ls -rtzwäre auf jeden fall nützlich. Vergleichen Sie die Alternative: superuser.com/a/294164/21402
Tobu

Antworten:

37

UPDATE (2014-02-02)

Dank unserer eigenen Entschlossenheit bei @ Anthon, das Fehlen dieser Funktion nachzuvollziehen , haben wir einen etwas formelleren Grund, warum diese Funktion fehlt, was ich zuvor erklärt habe:

Re: [PATCH] ls: adding --zero/-z option, including tests

From:      Pádraig Brady
Subject:   Re: [PATCH] ls: adding --zero/-z option, including tests
Date:      Mon, 03 Feb 2014 15:27:31 +0000

Vielen Dank für den Patch. Wenn wir dies tun würden, würden wir diese Schnittstelle verwenden. Ls ist jedoch wirklich ein Werkzeug zum direkten Verzehr durch einen Menschen, und in diesem Fall ist eine weitere Verarbeitung weniger nützlich. Für die weitere Verarbeitung ist find (1) besser geeignet. Das ist in der ersten Antwort unter dem obigen Link gut beschrieben.

Also wäre ich 70:30 gegen das Hinzufügen.

Meine ursprüngliche Antwort


Dies ist ein bisschen meine persönliche Meinung, aber ich glaube, dass es eine Designentscheidung ist, diesen Schalter nicht zu benutzen ls. Wenn Sie bemerken, dass der findBefehl diesen Schalter hat:

-print0
      True; print the full file name on the standard output, followed by a 
      null character (instead of the newline character that -print uses).  
      This allows file  names  that  contain  newlines or other types of white 
      space to be correctly interpreted by programs that process the find 
      output.  This option corresponds to the -0 option of xargs.

Wenn Sie diesen Schalter weglassen, deuten die Designer an, dass Sie die lsAusgabe nur für den menschlichen Verzehr verwenden sollten. Für die Weiterverarbeitung durch andere Tools sollten Sie findstattdessen verwenden.

Möglichkeiten zu finden

Wenn Sie nur nach alternativen Methoden suchen, finden Sie diese hier mit dem Titel: Richtige Vorgehensweise : Eine kurze Zusammenfassung . Von diesem Link sind dies wahrscheinlich die drei häufigsten Muster:

  1. Einfache Suche -exec; unhandlich, wenn COMMAND groß ist und 1 Prozess / Datei erstellt:
    find . -exec COMMAND... {} \;
  2. Einfache Suche -Exec mit +, schneller, wenn mehrere Dateien für COMMAND in Ordnung sind:
    find . -exec COMMAND... {} \+
  3. Verwenden Sie find und xargs mit \ 0-Trennzeichen

    (Nicht standardmäßige allgemeine Erweiterungen -print0 und -0. Funktioniert unter GNU, * BSDs, busybox)

    find . -print0 | xargs -0 COMMAND

Weitere Beweise?

Ich fand diesen Blog-Beitrag von Joey Hess 'Blog mit dem Titel: " ls: the missing options ". Einer der interessanten Kommentare in diesem Beitrag:

Der einzige offensichtliche Mangel ist jetzt die Option -z, mit der die Namen der Ausgabedateien auf NULL gesetzt werden sollten, damit sie von anderen Programmen verarbeitet werden können. Ich denke, das wäre einfach zu schreiben, aber ich war sehr beschäftigt mit IRL (viele Möbel bewegen) und bin nicht dazu gekommen. Gibt es Abnehmer, die es schreiben?

Bei der weiteren Suche habe ich dies in den Commit-Protokollen eines der zusätzlichen Schalter gefunden, die Joeys Blog-Post erwähnt: " Neues Ausgabeformat -j ". Es scheint also, als würde der Blog-Beitrag Spaß daran machen, jemals einen -zSchalter hinzuzufügen ls.

In Bezug auf die anderen Optionen stimmen mehrere Personen darin überein, dass -e nahezu nützlich ist, obwohl keiner von uns einen Grund finden kann, es zu verwenden. Mein Fehlerbericht hat es versäumt zu erwähnen, dass ls -eR sehr fehlerhaft ist. -j ist eindeutig ein Witz.

Verweise

slm
quelle
Vielen Dank. Ich bin mir der Vorbehalte bewusst. Keine Frage zu ls Ausgabeverarbeitung ist vollständig, ohne dass darauf hingewiesen wurde ;-)
Timo
@Timo - Das weiß ich, ich tat mehr für die künftigen Leser dieses Q. ich Sie auf der Website zu sehen, dass diese von nun 8- in Ihre Recherchen habe kommen würde)
slm
Das habe ich gemerkt und gut, dass du es getan hast. Ich hätte -0in meine Frage Hinweise darauf aufnehmen sollen, warum nicht (zumindest nicht, bis dies umgesetzt wurde), um die Menschen nicht in die Irre zu führen.
Timo
Unter der Annahme, dass ein Dateiname nichts wirklich Exotisches wie ein '\ n' enthält, ls -1 | tr '\012' '\000'werden Dateien durch NULL-Zeichen getrennt aufgelistet.
Samiam
2
Dieser Artikel befasst sich eingehend mit Problemen mit Dateinamen: dwheeler.com/essays/fixing-unix-linux-filenames.html
slm
20

Da die Antworten von @ slm auf die Ursprünge und möglichen Gründe eingehen, werde ich dies hier nicht wiederholen. Eine solche Option ist nicht in der Liste der abgelehnten Coreutils enthalten , aber der unten stehende Patch wird jetzt von Pádraig Brady abgelehnt, nachdem er an die Mailing-Liste von Coreutils gesendet wurde. Aus der Antwort geht hervor, dass dies ein philosophischer Grund ist (die lsAusgabe ist für den menschlichen Verzehr bestimmt).

Wenn Sie ausprobieren möchten, ob eine solche Option für Sie zumutbar ist, tun Sie Folgendes:

git clone git://git.sv.gnu.org/coreutils
cd coreutils
./bootstrap
./configure
make

Wenden Sie dann den folgenden Patch gegen commit an: b938b6e289ef78815935ffa705673a6a8b2ee98e dd 29.01.2014:

From 6413d5e2a488ecadb8b988c802fe0a5e5cb7d8f4 Mon Sep 17 00:00:00 2001
From: Anthon van der Neut <address@hidden>
Date: Mon, 3 Feb 2014 15:33:50 +0100
Subject: [PATCH] ls: adding --zero/-z option, including tests

* src/ls.c has the necessary changes to allow -z/--zero option to be
  specified, resulting in a NUL seperated list of files. This
  allows the output of e.g. "ls -rtz" to be piped into other programs

* tests/ls/no-args.sh was extended to test the -z option

* test/ls/rt-zero.sh was added to test both the long and short option
  together with "-t"

This patch was inspired by numerous questions on unix.stackexchange.com
where the output of ls was piped into some other program, invariably
resulting in someone pointing out that is an unsafe practise because of
possible newlines and other characters in the filenames.
---
 src/ls.c            |   31 +++++++++++++++++++++++++------
 tests/ls/no-arg.sh  |    7 ++++++-
 tests/ls/rt-zero.sh |   38 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+), 7 deletions(-)
 create mode 100755 tests/ls/rt-zero.sh

diff --git a/src/ls.c b/src/ls.c
index 5d87dd3..962e6bb 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -381,6 +381,7 @@ static int file_size_width;
    many_per_line for just names, many per line, sorted vertically.
    horizontal for just names, many per line, sorted horizontally.
    with_commas for just names, many per line, separated by commas.
+   with_zero for just names, one per line, separated by NUL.

-l (and other options that imply -l), -1, -C, -x and -m control

    this parameter.  */
@@ -391,7 +392,8 @@ enum format
     one_per_line,              /* -1 */
     many_per_line,             /* -C */
     horizontal,                        /* -x */
-    with_commas                        /* -m */
+    with_commas,               /* -m */
+    with_zero,                 /* -z */
   };

static enum format format;

@@ -842,6 +844,7 @@ static struct option const long_options[] =
   {"block-size", required_argument, NULL, BLOCK_SIZE_OPTION},
   {"context", no_argument, 0, 'Z'},
   {"author", no_argument, NULL, AUTHOR_OPTION},
+  {"zero", no_argument, NULL, 'z'},
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
   {NULL, 0, NULL, 0}
@@ -850,12 +853,12 @@ static struct option const long_options[] =
 static char const *const format_args[] =
 {
   "verbose", "long", "commas", "horizontal", "across",
-  "vertical", "single-column", NULL
+  "vertical", "single-column", "zero", NULL
 };
 static enum format const format_types[] =
 {
   long_format, long_format, with_commas, horizontal, horizontal,
-  many_per_line, one_per_line
+  many_per_line, one_per_line, with_zero
 };
 ARGMATCH_VERIFY (format_args, format_types);

@@ -1645,7 +1648,7 @@ decode_switches (int argc, char **argv)

     {
       int oi = -1;
       int c = getopt_long (argc, argv,
-                           "abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UXZ1",
+                           "abcdfghiklmnopqrstuvw:xzABCDFGHI:LNQRST:UXZ1",
                            long_options, &oi);
       if (c == -1)
         break;
@@ -1852,6 +1855,10 @@ decode_switches (int argc, char **argv)
             format = one_per_line;
           break;

+ case 'z':

+          format = with_zero;
+          break;
+
         case AUTHOR_OPTION:
           print_author = true;
           break;
@@ -2607,7 +2614,8 @@ print_dir (char const *name, char const *realname, bool 
command_line_arg)
                  ls uses constant memory while processing the entries of
                  this directory.  Useful when there are many (millions)
                  of entries in a directory.  */
-              if (format == one_per_line && sort_type == sort_none
+              if ((format == one_per_line || format == with_zero)
+                      && sort_type == sort_none
                       && !print_block_size && !recursive)
                 {
                   /* We must call sort_files in spite of
@@ -3598,6 +3606,14 @@ print_current_files (void)
         }
       break;

+ case with_zero:

+      for (i = 0; i < cwd_n_used; i++)
+        {
+          print_file_name_and_frills (sorted_file[i], 0);
+          putchar ('\0');
+        }
+      break;
+
     case many_per_line:
       print_many_per_line ();
       break;
@@ -4490,6 +4506,7 @@ print_many_per_line (void)
           indent (pos + name_length, pos + max_name_length);
           pos += max_name_length;
         }
+      putchar ('X'); // AvdN
       putchar ('\n');
     }
 }
@@ -4780,7 +4797,8 @@ Sort entries alphabetically if none of -cftuvSUX nor 
--sort is specified.\n\
   -F, --classify             append indicator (one of */=>@|) to entries\n\
       --file-type            likewise, except do not append '*'\n\
       --format=WORD          across -x, commas -m, horizontal -x, long -l,\n\
-                               single-column -1, verbose -l, vertical -C\n\
+                               single-column -1, verbose -l, vertical -C,\n\
+                               zeros -z\n\
       --full-time            like -l --time-style=full-iso\n\
 "), stdout);
       fputs (_("\
@@ -4888,6 +4906,7 @@ Sort entries alphabetically if none of -cftuvSUX nor 
--sort is specified.\n\
   -X                         sort alphabetically by entry extension\n\
   -Z, --context              print any security context of each file\n\
   -1                         list one file per line\n\
+  -z, --zero                 list files separated with NUL\n\
 "), stdout);
       fputs (HELP_OPTION_DESCRIPTION, stdout);
       fputs (VERSION_OPTION_DESCRIPTION, stdout);
diff --git a/tests/ls/no-arg.sh b/tests/ls/no-arg.sh
index e356a29..da28b96 100755
--- a/tests/ls/no-arg.sh
+++ b/tests/ls/no-arg.sh
@@ -30,11 +30,16 @@ out
 symlink
 EOF

-

 ls -1 > out || fail=1

compare exp out || fail=1 +/bin/echo -en "dir\00exp\00out\00symlink\00" > exp || framework_failure_

+
+ls --zero > out || fail=1
+
+compare exp out || fail=1
+
 cat > exp <<\EOF
 .:
 dir
diff --git a/tests/ls/rt-zero.sh b/tests/ls/rt-zero.sh
new file mode 100755
index 0000000..cdbd311
--- /dev/null
+++ b/tests/ls/rt-zero.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+# Make sure name is used as secondary key when sorting on mtime or ctime.
+
+# Copyright (C) 1998-2014 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_ ls touch
+
+date=1998-01-15
+
+touch -d "$date" c || framework_failure_
+touch -d "$date" a || framework_failure_
+touch -d "$date" b || framework_failure_
+
+
+ls -zt a b c > out || fail=1
+/bin/echo -en "a\00b\00c\00" > exp
+compare exp out || fail=1
+
+rm -rf out exp
+ls -rt --zero a b c > out || fail=1
+/bin/echo -en "c\00b\00a\00" > exp
+compare exp out || fail=1
+
+Exit $fail
--
1.7.9.5

Nach einem anderen make kannst du es testen mit:

  src/ls -rtz | xargs -0 -n1 src/ls -ld

Der Patch funktioniert also und ich kann keinen Grund dafür erkennen, aber das ist kein Beweis, dass es keinen technischen Grund gibt, die Option auszulassen. ls -R0macht vielleicht nicht viel Sinn, macht aber auch nicht ls -Rmdas , was man sofort machen lskann.

Anthon
quelle
Mit -zund --zeroist eher im Einklang mit Art (auch in Coreutils.
Anthon