この質問は、ls
'-1
オプションに関する質問と、ls
の出力の処理を含む、質問と回答を求める傾向が繰り返し現れる傾向にあります。
この出力の再利用ls
は理解できるようです。たとえば、ls
を使用してファイルのリストを並べ替える方法を知っている場合は、出力を別の方法の入力として使用することができます。
これらのQ&Aに、適切に動作するファイル名(スペースや改行などの特殊文字は含まない)で構成されるファイル名リストへの参照が含まれていない場合、そこでコマンドシーケンスが機能しない危険性を指摘するコメントが頻繁に寄せられます。改行、スペースなどのファイルです.
find
、sort
、およびその他のユーティリティは、「難しい」ファイル名を通信するという問題を解決します。 xargs
Unix/Linuxファイルシステムでは、ファイル名の有効な文字ではないNUL文字/バイト(/
?に加えて唯一の文字)でファイル名を区切るオプションを使用する。
ls
のマニュアルページとls --help
の出力(より多くのオプションがリストされています)を調べたところ、ls
(coreutils
から)に指定するオプションがないことがわかりましたNULで区切られた出力。 「改行で区切られた出力ファイル名」)として解釈できる-1
オプションがあります。
[〜#〜] q [〜#〜]:ls
に「NULで区切られたファイル名を出力する--zero
または-0
オプションがない理由には、技術的または哲学的な理由がありますか? 「?
ファイル名のみを出力する(そして-l
を使用しないなど)何かをする場合、それは理にかなっています:
ls -rt -0 | xargs -r0 …
私はこれが機能しない理由を欠落している可能性があります、または私が見落としたこの例の代替策がありますそしてそれはそれほど複雑ではなく、そして/または不明瞭ではありません。
補遺:
ls -lrt -0
を実行してもあまり意味がありませんが、find . -ls -print0
を使用しない場合と同じように、-0
/-z
/--zero
オプションを指定しない理由にはなりません。
私たち自身の @ Anthon's での決定 この機能の欠如に続いて のおかげで、この機能が欠けている理由について、もう少し正式な理由があります。前に説明しました:
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つのより一般的なパターンです:
find . -exec COMMAND... {} \;
find . -exec COMMAND... {} \+
(非標準の共通拡張-print0および-0。GNU、* BSD、busyboxで動作します)
find . -print0 | xargs -0 COMMAND
Joey Hessのブログからこのブログ投稿を見つけました: " ls:The missing options "。この投稿の興味深いコメントの1つ:
現時点で明らかな唯一の欠如は、-zオプションです。これにより、他のプログラムによる制約のために、出力ファイル名がNULLで終了するはずです。これは簡単に書くことができると思いますが、私はIRL(家具をたくさん動かすこと)で忙しく、それを理解できませんでした。それを書く人はいますか?
さらに検索したところ、Joeyのブログ投稿で言及されている追加スイッチの1つである「 新しい出力形式-j 」のコミットログでこれが見つかりました。 -z
スイッチをls
に追加したことはありません。
他のオプションに関しては、複数の人が-eがほぼ有用であることに同意していますが、それを使用する理由を見つけることはできません。私のバグレポートでは、ls -eRは非常にバグが多いことを無視しています。 -jは明らかに冗談です。
@slmの回答が起源と考えられる理由に入るので、ここでは繰り返しません。そのようなオプションは、coreutils 拒否された機能のリスト ではではありませんですが、以下のパッチ is現在はPádraigBradyによって拒否されています 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
別のmakeの後、次のようにテストできます。
src/ls -rtz | xargs -0 -n1 src/ls -ld
そのため、パッチは機能し、機能しない理由はわかりませんが、それはオプションを除外する技術的理由がないことを証明するものではありません。 ls -R0
はあまり意味をなさないかもしれませんが、ls
がそのまま使用できるls -Rm
も意味がありません。
GNU xargs(coreutilsから))がある場合、次のコマンドを実行できます。
$ ls … |xargs -d "\n" …
それ以外の場合は、xargs
のバージョンが-0
をサポートしていることを確認した後(ほとんどはサポートしますが、 xargsのPOSIX仕様 はそれに言及していません)、次のコマンドを実行できます。
$ ls … |tr "\n" "\000" |xargs -0 …
私の~/.aliases
と~/.bashrc
から入手した~/.zshrc
ファイルには、使用しているすべてのシステムに存在する(したがって、広範な互換性が必要です)には次のものが含まれます。
# Like `find ... -print0 |xargs -0` for programs that don't have a -print0
xargsn() { # defer definition until first use
if xargs --help 2>&1 |grep -Fqw "d, --delimiter"; then # GNU
xargsn() { xargs -d "\n" "$@"; }
else
# warning, xargs -0 isn't POSIX, but GNU, BSD/OSX, and Busybox support it
xargsn() { tr "\n" "\000" |xargs -0 "$@"; }
fi
xargsn "$@"
}
if command -v compdef >/dev/null 2>&1; then compdef xargsn=xargs; fi # for zsh
これにより、xargsn
を初めて実行するまでxargs --help
の呼び出しが延期され、(かなり長い)エイリアスファイルが高速化されます。つまり、GNU xargsをチェックします定義を設定した後(これは非常に高速で、約0.02秒)、最初の要求を1回限りの再帰呼び出しとして完了します。
その最後の行は、Z-Shellにxargsn
をあたかもxargs
であるかのように完了するように指示します(あるため)。
このxargsn
関数は、改行を含む可能性のあるアイテムを繰り返し処理しない限り、どのコマンドでも機能します。警告:多くのファイルシステムのファイル名には、技術的に改行を含めることができます。このようなファイル名を使用している場合は、致命的な事態が発生しないようにしてください。 (「ls
を解析しない」引数も参照してください。)