มีเหตุผลหรือไม่ที่ ls ไม่มีตัวเลือก --zero หรือ -0


37

คำถามนี้ได้รับแจ้งจากคำถามเกี่ยวกับls' ตัวเลือกและแนวโน้มที่เกิดขึ้นของคนที่จะถามคำถามและคำตอบที่มีการประมวลผลการส่งออกของ-1ls

การใช้งานเอาต์พุตนี้lsดูเหมือนจะเข้าใจได้เช่น: หากคุณรู้วิธีเรียงลำดับรายการไฟล์ด้วยlsคุณอาจต้องการใช้ผลลัพธ์ในลักษณะนั้นเป็นอินพุตสำหรับอย่างอื่น

หากคำถาม & คำตอบเหล่านั้นไม่ได้มีการอ้างอิงไปยังรายการชื่อไฟล์ที่สร้างขึ้นซึ่งประกอบด้วยชื่อไฟล์ที่ประพฤติดี (ไม่มีอักขระพิเศษเช่นช่องว่างและการขึ้นบรรทัดใหม่) พวกเขามักถูกวิจารณ์โดยบางคนที่ชี้ให้เห็นถึงอันตรายของลำดับคำสั่ง เป็นไฟล์ที่มีบรรทัดใหม่เว้นวรรคและอื่น ๆ

find, sortและสาธารณูปโภคอื่น ๆ ในการแก้ปัญหาของการสื่อสาร "ยาก" ชื่อไฟล์เช่นxargsโดยใช้ตัวเลือกในการแยกชื่อไฟล์ที่มีตัวละคร NUL / ไบต์ซึ่งไม่ได้เป็นตัวละครที่ถูกต้องในชื่อไฟล์ (เพียงคนเดียวที่นอกเหนือไป/?) บน ระบบไฟล์ Unix / Linux

ฉันมองไปที่หน้า man สำหรับlsและ output สำหรับls --help(ซึ่งมีตัวเลือกเพิ่มเติมในรายการ) และไม่พบว่าls(จากcoreutils) มีตัวเลือกเพื่อระบุ NUL output ที่แยกออก มันมี-1ตัวเลือกที่สามารถตีความได้ว่า"ชื่อไฟล์เอาต์พุตคั่นด้วยขึ้นบรรทัดใหม่" )

ถาม : มีเหตุผลทางเทคนิคหรือปรัชญาทำไมlsไม่มีตัวเลือก--zeroหรือ-0ที่จะ "ชื่อไฟล์เอาต์พุตคั่นด้วย NUL"?

หากคุณทำสิ่งที่ส่งออกเฉพาะชื่อไฟล์ (และไม่ใช้เช่น-l) ที่เหมาะสม:

ls -rt -0 | xargs -r0 

ฉันอาจจะพลาดอะไรบางอย่างไปทำไมมันถึงไม่ทำงานหรือมีทางเลือกอื่นสำหรับตัวอย่างนี้ที่ฉันมองข้ามและนั่นก็ไม่ซับซ้อนและ / หรือคลุมเครือมากขึ้น


ภาคผนวก:

การทำls -lrt -0อาจจะไม่ได้ทำให้รู้สึกมาก แต่ในลักษณะเดียวกับที่find . -ls -print0ไม่ได้ดังนั้นที่ไม่ได้เป็นเหตุผลที่จะไม่ให้เป็น-0/ -z/ --zeroตัวเลือก


สิ่งที่ชัดเจนที่ต้องทำคือเขียนและถามผู้ดูแล coreutils ของ GNU ว่าความคิดของเขาเกี่ยวกับตัวเลือกนั้นคืออะไร
Faheem Mitha

1
ls -rtzจะเป็นประโยชน์อย่างแน่นอน ตัดกันทางเลือก: superuser.com/a/294164/21402
Tobu

คำตอบ:


37

อัปเดต (2014-02-02)

ขอบคุณที่แอนตั้นมีความมุ่งมั่นในการติดตามการขาดคุณสมบัตินี้เรามีเหตุผลที่เป็นทางการเล็กน้อยว่าทำไมฟีเจอร์นี้ถึงขาดไปซึ่งย้ำสิ่งที่ฉันอธิบายไว้ก่อนหน้านี้:

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; เทอะทะถ้าคำสั่งมีขนาดใหญ่และสร้าง 1 กระบวนการ / ไฟล์:
    find . -exec COMMAND... {} \;
  2. ค้นหา -exec ด้วย + ง่ายกว่าหากไฟล์หลายไฟล์ใช้ได้สำหรับคำสั่ง:
    find . -exec COMMAND... {} \+
  3. ใช้ find และ xargs พร้อมตัวคั่น \ 0

    (ส่วนขยายทั่วไปที่ไม่เป็นมาตรฐาน -print0 และ -0 ทำงานบน GNU, * BSDs, busybox)

    find . -print0 | xargs -0 COMMAND

หลักฐานเพิ่มเติม?

ฉันพบโพสต์บล็อกนี้จากบล็อกของ Joey Hess ที่ชื่อ: " ls: ตัวเลือกที่หายไป " หนึ่งในความคิดเห็นที่น่าสนใจในโพสต์นี้:

การขาดชัดเจนเท่านั้นตอนนี้เป็นตัวเลือก -z ซึ่งควรทำให้ชื่อไฟล์ที่ส่งออกเป็นโมฆะสำหรับการ consuption โดยโปรแกรมอื่น ๆ ฉันคิดว่ามันจะง่ายต่อการเขียน แต่ฉันยุ่งมากกับ IRL (ย้ายเฟอร์นิเจอร์จำนวนมาก) และไม่ได้ไป ผู้รับใด ๆ ที่จะเขียนมัน?

การค้นหาเพิ่มเติมฉันพบนี้ในบันทึกการกระทำจากหนึ่งในสวิทช์เพิ่มเติมที่โพสต์บล็อกของโจอี้กล่าว " ผลลัพธ์รูปแบบใหม่ -j " ดังนั้นจึงจะดูเหมือนว่าโพสต์บล็อกได้สนุกกับความคิดของที่เคยเพิ่มที่สลับไป-zls

สำหรับตัวเลือกอื่น ๆ หลาย ๆ คนยอมรับว่า -e เกือบจะมีประโยชน์เกือบถึงแม้ว่าเราจะไม่สามารถหาเหตุผลได้เลย รายงานข้อผิดพลาดของฉันละเลยที่จะพูดถึงว่า ls -eR เป็นรถบั๊กกี้มาก -j เป็นเรื่องตลกอย่างชัดเจน

อ้างอิง


ขอขอบคุณ. ฉันรู้เรื่องคำเตือน ไม่มีคำถามเกี่ยวกับการประมวลผล ls ที่เสร็จสมบูรณ์โดยไม่ต้องระบุ ;-)
ติโม

@Timo - ฉันรู้ว่าคุณทำฉันทำมากขึ้นสำหรับผู้อ่านในอนาคตของคำถามนี้ฉันเห็นคุณในเว็บไซต์ว่าสิ่งเหล่านี้จะเกิดขึ้นในการค้นหาของคุณตอนนี้ 8-)
slm

ฉันรู้ว่าและสิ่งที่ดีที่คุณทำ ฉันควรจะมีการอ้างอิงถึงสาเหตุที่ไม่ (อย่างน้อยก็จนกว่า-0จะมีการใช้งาน) ในคำถามของฉันเพื่อไม่ให้คนหลงทาง
Timo

แน่นอนว่าไม่มีอะไรแปลกใหม่อย่างแท้จริงเช่น '\ n' ในชื่อไฟล์ls -1 | tr '\012' '\000'จะแสดงรายการไฟล์ที่คั่นด้วยอักขระ NULL
samiam

2
บทความนี้จะกล่าวถึงส่วนลึกของปัญหาการตั้งชื่อไฟล์: dwheeler.com/essays/fixing-unix-linux-filenames.html
slm

20

เมื่อคำตอบของ @ slm เข้าสู่ที่มาและสาเหตุที่เป็นไปได้ฉันจะไม่ทำซ้ำที่นี่ ตัวเลือกดังกล่าวไม่ได้อยู่ในรายการคุณลักษณะ coreutils ที่ถูกปฏิเสธแต่แพทช์ด้านล่างถูก ปฏิเสธโดยPádraig 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.