ls에 --zero 또는 -0 옵션이없는 이유가 있습니까?


37

이 질문은 ls' -1옵션에 대한 질문과 사람들이 출력을 처리하는 것을 포함하여 질문과 답변을 묻는 반복되는 경향에 의해 촉발되었습니다 ls.

이 출력 재사용은 ls이해할 수있는 것처럼 보입니다. 예를 들어 파일 목록을 정렬하는 방법을 알고 있다면 ls출력을 다른 방식의 입력으로 사용할 수도 있습니다.

이러한 Q & A에 멋지게 동작하는 파일 이름 (공백 및 줄 바꿈과 같은 특수 문자 없음)으로 구성된 파일 이름 목록에 대한 참조가 포함되어 있지 않은 경우, 명령 시퀀스의 위험이 있음을 지적하는 사람이 종종 주석을 달았습니다. 줄 바꿈, 공백 등이있는 파일입니다.

find, sort및 기타 유틸리티 등은 "어려운"파일 이름을 통신 문제 해결 xargs파일 이름에 유효한 문자하지 않은 NUL 문자 / 바이트로 파일 이름을 구분하는 옵션을 사용하여 (외에 유일한 사람 /?)에 유닉스 / 리눅스 파일 시스템.

나는 맨 페이지 ls와 출력 ls --help(더 많은 옵션이 나열되어 있음)을보고 ls(from coreutils)에 NUL로 구분 된 출력을 지정하는 옵션이 있음을 찾을 수 없었습니다 . "개행으로 분리 된 출력 파일 이름"-1 으로 해석 될 수 있는 옵션이 있습니다 )

Q : "파일 이름을 NUL로 구분하여 출력하는" 또는 옵션 ls이없는 기술적 또는 철학적 이유 가 있습니까?--zero-0

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

답변:


37

업데이트 (2014-02-02)

이 기능이 부족한 것에 대한 우리 자신의 @Anthon의 결정 덕분에 우리 는이 기능 이 왜 부족한 지에 대해 약간 더 공식적인 이유가 있습니다.

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는 실제로 사람이 직접 소비하는 도구이며,이 경우 추가 처리가 덜 유용합니다. 추가 처리의 경우 find (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. 간단한 찾기-실행; COMMAND가 크면 처리가 어렵고 1 개의 프로세스 / 파일을 만듭니다.
    find . -exec COMMAND... {} \;
  2. COMMAND에 여러 파일이 적합하면 +로 간단한 찾기 -exec :
    find . -exec COMMAND... {} \+
  3. \ 0 구분 기호로 find 및 xargs 사용

    (비표준 공통 확장자 -print0 및 -0. GNU, * BSDs, busybox에서 작동)

    find . -print0 | xargs -0 COMMAND

추가 증거?

Joey Hess의 블로그에서 " ls : missing options " 라는 제목의 블로그 게시물을 찾았습니다 . 이 게시물의 흥미로운 의견 중 하나 :

현재 유일하게 부족한 것은 -z 옵션이며, 다른 프로그램에서 사용하기 위해 출력 파일 이름을 NULL로 종료해야합니다. 나는 이것이 쓰기 쉽다고 생각하지만, IRL (많은 가구를 옮기는 것)으로 바빴고 그것을 얻지 못했습니다. 그것을 쓰는 사람이 있습니까?

추가 검색 나는 Joey의 블로그 게시물이 언급 한 추가 스위치 중 하나 인 " new output format -j " 의 커밋 로그에서이를 발견 했으므로 블로그 게시물에 -z스위치를 추가한다는 개념에서 재미를 느끼고있는 것 같습니다 ls.

다른 옵션과 관련하여 여러 사람들은 -e가 거의 유용하지만 우리 중 누구도 그것을 사용할 이유를 찾을 수는 없다고 동의합니다. 내 버그 보고서는 ls -eR이 매우 버그가 있다고 언급하지 않았습니다. -j는 분명히 농담입니다.

참고 문헌


감사합니다. 나는주의 사항을 알고 있습니다. ls 출력 처리에 대한 의문의 여지없이 ;-)
Timo

당신이 할 나도 알아, 내가) 지금 8 이러한 귀하의 검색에 왔어요 것보다 내가 사이트에 당신을보고이 Q. 미래의 독자를 위해 일을했다 - @Timo
SLM을

나는 그것을 깨달았고 당신이 한 것이 좋다. -0사람들을 타인으로 이끌지 않기 위해 내 질문 에 왜 (적어도 구현 되지 않을 때까지 ) 하지 않은지에 대한 언급을 포함시켜야했습니다 .
Timo

물론 파일 이름에 '\ n'과 같은 이국적인 것이 없다고 가정하면 ls -1 | tr '\012' '\000'파일을 NULL 문자로 구분하여 나열합니다.
samiam

2
이 기사에서는 파일 이름 지정 문제에 대해 자세히 설명
slm

20

@ slm의 답변이 기원과 가능한 이유에 들어가기 때문에 여기서 반복하지 않습니다. 이러한 옵션은 하지 로 coreutils에 기능 목록을 거부 하지만, 아래의 패치가 되어 지금 파드 리그 브래디에 의해 거부 메일 링리스트로 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.