Чи є причина, чому ls не має опції --zero або -0


37

Це питання було викликано питаннями про ls" -1опції і повторюваних тенденції людей ставити запитання і відповіді , які включають в себе обробку виведення ls.

Це повторне використання виводу lsздається зрозумілим, наприклад: якщо ви знаєте, як сортувати список файлів за допомогою ls, можливо, ви хочете використовувати вихід таким чином як вхід для чогось іншого.

Якщо ці запитання не містять посилання на список імен файлів, що складається з добре поводяться імен файлів (відсутні спеціальні символи, такі як пробіли та нові рядки), їх часто коментує хтось, вказуючи на небезпеку того, що командна послідовність не працює, коли там - це файли з новими рядками, пробілами тощо.

find, sortа також інші утиліти вирішують проблему передачі "складних" імен файлів, наприклад xargs, використовуючи опцію відокремлення імен файлів символом / байтом NUL, який не є дійсним символом у імені файлу (єдиному на додаток до /?) на Файлові системи Unix / Linux

Я переглянув сторінку man для lsта вихід для ls --help(який має більше перелічених параметрів) і не зміг знайти, що lscoreutils) має можливість вказати вихідний розділений вихід NUL. У нього є -1опція, яку можна інтерпретувати як "імена вихідних файлів, розділених новим рядком" )

Питання : Чи є технічна чи філософська причина, чому lsнемає --zeroабо -0опції, яка б "виводила імена файлів, розділених NUL"?

Якщо ви робите щось, що виводить лише імена файлів (а не використовують напр. -l), Це може мати сенс:

ls -rt -0 | xargs -r0 

Я міг би пропустити щось, чому це не вийде, або є альтернатива для цього прикладу, яку я не помітив, і це не набагато складніше та / або незрозуміло .


Додаток:

Робити це, ls -lrt -0мабуть, не має особливого сенсу, але так само, як find . -ls -print0це не відбувається, так що це не привід не надавати варіант -0/ -z/ --zero.


Очевидно, що потрібно зробити - написати та запитати у технічного керівника GNU coreutils, що він думає про такий варіант.
Faheem Mitha

1
ls -rtzнапевно було б корисно. Контрактуйте альтернативу: superuser.com/a/294164/21402
Тобу

Відповіді:


37

ОНОВЛЕННЯ (02.02.2014)

Завдяки нашій власній рішучості @ Ентона у відслідковуванні відсутності цієї функції , у нас є дещо формальніша причина, чому ця функція відсутня, яка ще раз повторює те, що я пояснював раніше:

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

Дякую за патч. Якби ми це робили, то це був би інтерфейс, який ми використовуємо. Однак ls - це справді інструмент прямого споживання людиною, і в цьому випадку подальша обробка є менш корисною. Для подальшої обробки більш підходить пошук (1). Це добре описано в першій відповіді за посиланням вище.

Тож я б за 70:30 не додав цього.

Моя оригінальна відповідь


Це трохи моя особиста думка, але я вважаю, що це рішення дизайну для відключення цього вимикача ls. Якщо ви помітили, що findкоманда має цей перемикач:

-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.

Залишаючи цей вимикач, дизайнери натякали на те, що ви не повинні використовувати lsвихід для нічого, крім споживання людиною. Для подальшої обробки іншими інструментами ви повинні використовуватиfind .

Способи використання знахідки

Якщо ви просто шукаєте альтернативні методи, ви можете знайти їх тут під назвою: Робити це правильно: Швидкий підсумок . З цього посилання, ймовірно, є 3 більш поширені моделі:

  1. Проста знахідка -exec; невміло, якщо COMMAND великий, і створює 1 процес / файл:
    find . -exec COMMAND... {} \;
  2. Просте знаходження -exec з +, швидше, якщо для КОМАНДИ декілька файлів добре:
    find . -exec COMMAND... {} \+
  3. Використовуйте знахідки та xargs з \ 0 роздільниками

    (нестандартні поширені розширення -print0 і -0. Працює в GNU, * BSD, busybox)

    find . -print0 | xargs -0 COMMAND

Подальші докази?

Я знайшов цю публікацію в блозі Джої Гесса під назвою: " ls: відсутні варіанти ". Один із цікавих коментарів у цій публікації:

Єдиний очевидний недолік зараз - опція -z, яка повинна змусити вихідні назви файлів бути NULL припиненими для використання в інших програмах. Я думаю, що це було б легко написати, але я був надзвичайно зайнятий IRL (рухався багато меблів) і не потрапив до нього. Хто-небудь, хто бере його, щоб написати?

Подальший пошук я виявив це в журналах фіксування з одного з додаткових комутаторів, про які йдеться у публікації блогу Джої, " новий вихідний формат -j ", тож здавалося б, що повідомлення в блозі розважалося над поняттям коли-небудь додавати -zкомутатор ls.

Щодо інших варіантів, багато людей сходяться на думці, що -e майже майже корисний, хоча ніхто з нас не може знайти причину його використовувати. У моєму звіті про помилки нехтувалося зазначити, що ls -eR дуже баггі. -j явно жарт.

Список літератури


Дякую. Мені відомо про застереження. Ніякого питання щодо обробки виводу ls не завершено, не зазначивши про це ;-)
Тимо

@Timo - Я знаю, що ви робите, я робив більше для майбутніх читачів цього питання. Я бачу вас на сайті, що вони вже знайшли б ваші пошуки 8–8)
slm

Я зрозумів це, і добре, що ти зробив. Я повинен був включити посилання на те, чому б цього не було (принаймні, до тих пір, поки -0це не буде здійснено) у моєму питанні, щоб не заблукати людей.
Тимо

Звичайно, якщо припустити, що в імені файлу немає нічого насправді екзотичного, як-от "\ n", ls -1 | tr '\012' '\000'список файлів, розділених символами NULL.
саміам

2
Ця стаття заглиблюється в глибину проблем з іменами
slm

20

Оскільки відповіді @ slm входять у витоки та можливі причини, я не повторю це тут. Такий варіант НЕ на Coreutils відхиленого список функцій , але нижче патч в даний відкинутий Padraig Brady після відправки його в Coreutils списку розсилки. З відповіді видно, що це філософська причина ( lsвихід призначений для споживання людиною).

Якщо ви хочете спробувати, чи підходить такий варіант для себе, зробіть:

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

то застосуйте наступний патч проти фіксувати b938b6e289ef78815935ffa705673a6a8b2ee98e dd 2014-01-29:

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

Після іншого виготовлення ви можете протестувати його за допомогою:

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

Таким чином, патч працює, і я не можу побачити причину, чому він цього не зробив, але це не підтвердження, що немає технічних причин залишати варіант. ls -R0не може не мати великого сенсу, але і робить , ls -Rmякий lsможе зробити з коробки.


Наявність -zі --zeroбільше відповідає сорту (також у coreutils.
Anthon
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.