为什么 'ls' 突然用单引号中的空格包裹项目?

Wya*_*ard 226 ls debian coreutils upgrade quoting

我只是注意到,在我的一台机器上(运行 Debian Sid),每当我输入ls任何带空格的文件名时,它周围都有单引号。

我立即检查了我的别名,却发现它们完好无损。

wyatt@debian630:~/testdir$ ls
'test 1.txt'  test1.txt
wyatt@debian630:~/testdir$ alias
alias ls='ls --color=auto'
alias wget='wget --content-disposition'
wyatt@debian630:~/testdir$
Run Code Online (Sandbox Code Playgroud)

(图片)

另一个测试,文件名中包含单引号(也回答了 jimmij 的请求):

wyatt@debian630:~/testdir$ ls
'test 1.txt'  test1.txt  'thishasasinglequotehere'\''.txt'
wyatt@debian630:~/testdir$ touch "'test 1.txt'"
wyatt@debian630:~/testdir$ ls
''\''test 1.txt'\'''  test1.txt
'test 1.txt'          'thishasasinglequotehere'\''.txt'
Run Code Online (Sandbox Code Playgroud)

(图片)

使用新的 coreutils-8.26 输出进行更新(诚然,这不那么令人困惑,但默认情况下仍然令人恼火)。感谢 Pádraig Brady 提供此打印输出:

$ ls
"'test 1.txt'"   test1.txt
'test 1.txt'    "thishasasinglequotehere'.txt"

$ ls -N
'test 1.txt'  test1.txt
test 1.txt    thishasasinglequotehere'.txt
Run Code Online (Sandbox Code Playgroud)

为什么会这样?我如何正确停止它?

需要明确的是,我自己将 ls 设置为自动彩色输出。它从来没有在事物周围加上引号。

我正在运行bash,coreutils 8.25。

有什么方法可以在不重新编译的情况下解决这个问题?

编辑:出现 coreutils 开发人员选择)打破惯例并将其设为全局默认值。


更新 - 2017 年 10 月 - 默认情况下,Debian Sid 已重新启用 shell 转义引用。https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=877582

在对上一个错误报告的回复链的底部,“更改是有意的,并将保留。” https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=813164#226

我以为这已经解决了,但显然它只是恢复了,以便“稳定”的 Debian 分支可以保持其“功能冻结”,同时从新版本中获取其他修复等。所以这是一种耻辱(在我看来)。

更新:2019 年 4 月:刚刚在 PHP中发现了一个由ls. 当您让开发人员感到困惑并生成错误的错误报告时,我认为可能是时候重新评估您的更改了。

更新:Android toyboxls现在正在做类似的事情,但使用反斜杠而不是引号。使用 -q 选项使空格呈现为“问号字符”(我没有检查它们是什么,因为它们显然不是空格),所以到目前为止我找到的唯一解决方法是添加将其写入脚本并在启动 shell 时获取它。此函数ls在终端中使用列,否则每行打印一个,同时ls由于它通过管道运行而逐字打印空间。

ls() {
    # only way I can stop ls from escaping with backslashes
    if [ -t 1 ]; then
        /system/bin/ls -C $@ |cat
    else
        /system/bin/ls $@ |cat
    fi
}
Run Code Online (Sandbox Code Playgroud)

Jan*_*lik 145

前言:虽然为这样的答案投票并收工可能会非常令人满意,但请放心,GNU coreutils 维护者并不关心 SO 答案投票,如果您真的想鼓励他们改变,您需要按照这个答案的描述给他们发电子邮件


2019 年更新
去年的某个时候,维护人员加倍努力,现在向任何 bug-coreutils@gnu.org 报告有关此问题的报告仅提供样板响应,指向他们网站上的一个令人难以置信的长页面,列出了人们对此更改遇到的问题他们已经承诺无视
来自 bug-coreutils@gnu.org 报告的持续压力显然产生了影响,迫使生成这个巨大而荒谬的页面,并可能将愿意处理该问题的维护者数量减少到只有一个。
当这么多人认为一个事情是一个错误时,那么无论维护者是否不同意,它都是一个错误。
继续给他们发电子邮件仍然是鼓励改变的最简单方法。


为什么会这样?

几个 coreutils 维护者认为他们比几十年的事实标准更了解。


我该如何正确阻止它?

http://www.gnu.org/software/coreutils/coreutils.html

错误报告

如果您认为您在 Coreutils 中发现了错误,请尽可能完整地将错误报告发送到<bug-coreutils@gnu.org>,它将自动输入到 Coreutils 错误跟踪器中。在报告错误之前,请阅读常见问题解答。关于如何编写错误报告和提出好的问题的一个非常有用且经常被引用的指南是文档如何以聪明的方式提出问题。您可以浏览以前的帖子并搜索 bug-coreutils 存档。

已经恢复的发行版?这个变化:

发行版不受影响:

  • openSUSE(已使用 -N)

“有什么办法不用重新编译就可以解决这个问题?

支持者会让你...

通过将 -N 添加到他们的 ls 别名来恢复到旧格式

......在你所有的安装上,在任何地方,在永恒的剩余时间里。

  • 作为使用 *nix 系统 30 年的人,我发现像这样无端的更改非常烦人。一方面,他们打破了长期存在的脚本。他们还违反了最小惊讶原则。如上所述,“选择加入”应该是此处的默认设置。 (65认同)
  • @PádraigBrady 这种变化让我很烦恼,并浪费了几个小时来寻找原因和解决方案。我并不是要消极 - 我只是分享另一个人的观点!修改核心行为具有巨大的影响。 (52认同)
  • @PádraigBrady 更新答案。但是,在您的 coreutils 线程中看到大量拒绝。底线是你正在为人们创造更多的工作,而且你是以一个操作系统的名义做的,这个操作系统是 1970 年操作系统的克隆。如果人们想要不同的东西,他们会选择加入。 (42认同)
  • @PádraigBrady 这仍然不是推动此类变化的方式。默认情况下选择加入而不是激活该行为会*方式*更具建设性。它还错误地暗示这是文件名的存储方式,简而言之,在 `ls` 中,您不再看到它是如何存储的。该功能**应该**是可选的,**不是**默认值。 (33认同)
  • 该更改是在邮件列表中提出的,并且得到了三位 coreutils 维护者的认可,认为这是一项净收益。我们完全愿意就此提出建设性的论点。这毕竟是开源的,我们不是要发号施令,只是为了改进。请随时在 http://lists.gnu.org/archive/html/coreutils/2016-02/msg00000.html 的 coreutils 线程中回复(顺便说一句,有一个建设性的建议来改进其中一个美学那里提到的缺点,通过添加空间来改善对齐) (20认同)
  • 我浪费了几个小时试图用正则表达式重命名那些该死的文件...... (8认同)
  • @BrianClapper “一方面,他们打破了长期存在的脚本。” – 我也不喜欢这种变化,但**为什么**你甚至首先在脚本中解析 `ls` 的输出?此外,不,它不会破坏脚本,因为它仅在输出到终端时才会这样做。 (6认同)
  • @RogerDahl 即使你没有使用`-l`,输出已经在列中,所以它仍然只会增加噪音......这就是我现在在这里的原因。 (5认同)
  • 我不责怪发行版维护者,我实际上赞扬他们与这些人打交道并设法在这里提供健全的软件。我为他们暂时解决这个问题而鼓掌。我将 `-N` 应用于我的别名,但说真的,这到底是怎么回事。 (4认同)
  • @JanKyuPeblik 尚未恢复此更改的发行版包括 Gentoo 和(如果重要的话)Cygwin。也大概是 Red Hat(因为 Cygwin 由 Red Hat 的人管理)。不确定是否要将它们添加到列表中。 (3认同)
  • 选择退出不好,选择加入好。但显然 coreutils 开发人员更喜欢自动添加到邮件列表中,并可以选择稍后退出。对,没错。 (3认同)
  • 关于开发商的声明需要来源。 (2认同)
  • 有谁知道 coreutils 跟踪器中是否存在有关此更改的活动错误?是否有一种明智的方式来反对这种更改后的默认值? (2认同)
  • @Wyatt8740 由于它会影响所有发行版(即使是那些明智到目前已经避免使用它的发行版),我认为最简单的方法是仅列出那些无需担心的发行版。&lt;耸肩&gt; (2认同)
  • @Wyatt8740 我的哀悼。文字已更新。我对他使用“矛盾的”这个词时他的意思可能是“冷漠”感到非常矛盾,而且一般来说,为什么公共服务中的人会从漠不关心的角度运作;这与 IMO 的观点大致相反。 (2认同)
  • 感谢您通过电子邮件发送错误跟踪器的冲动更新此内容。如果不恢复,这会让我发疯。 (2认同)
  • 我对 `ls` 的别名包括 `-l`,它在单独的行中列出每个文件。额外的引用只会增加噪音。显然,这应该是一个选择加入。然后,Debian 可以通过在默认的 `.bashrc` 中添加一个开关来启用它。 (2认同)

cuo*_*glm 127

您可以选择引用样式

ls --quoting-style=literal
Run Code Online (Sandbox Code Playgroud)

等同于:

ls -N
Run Code Online (Sandbox Code Playgroud)

或者:

QUOTING_STYLE=literal ls
Run Code Online (Sandbox Code Playgroud)

将其设为别名,或export QUOTING_STYLE=literal在您的设置中设置.bashrc以实现 8.25 之前的行为。

  • 似乎有点奇怪我必须这样做才能获得正常的 unix-y 行为。另外,我想要旧的默认值。我不认为转义是旧的默认设置 - 我认为它打印的正是实际存在的内容。 (17认同)
  • 对于 8.25 之前的行为,请在 bashrc 中使用 `export QUOTING_STYLE=literal`。 (11认同)
  • 这个答案值得更多赞成。它直接解决了提问者提出的问题,避免了官僚主义的回答。事实上,环境变量方法看起来很优雅。(我个人更喜欢新行为,因为它有利于更有效的 C&amp;P 操作),但是,ls 足够聪明,可以在使用重定向时以旧方式运行,因此不会对使用 ls 输出的脚本造成伤害。 (8认同)
  • 或使用`-N`,似乎。我只是在编译我自己的版本,因为我已经设置了一个个人存储库。 (3认同)
  • @LSpice 我已经编辑了帖子以使用 `literal` 而不是 `escape`(我相信 @cuonglm 只是想展示如何更改样式,而不是专门针对 `escape` 样式)。 (2认同)

Pád*_*ady 52

关于变化的几点说明。

  • 它是在 coreutils v8.25 中引入的,并且在 v8.26 中改进了对齐
  • 它仅在输出到终端时发生,因此不会破坏脚本
  • 它消除了用户对包含空格的文件的输出的歧义
  • 它清理输出,因此复制和粘贴是安全的
  • 输出现在对于复制并粘贴回 shell始终有效
  • 用户可以通过将 -N 添加到他们的 ls 别名来恢复到旧格式

  • 我很抱歉 - 显然您至少安全地引用了 shell 引用。我还是不喜欢。选项很好 - 但是以降低其准确性的方式改变已有数十年历史的 unix 核心实用程序的非常明确的默认行为只能是一个*坏*主意。 (13认同)
  • 我的最后一个例子是不是含糊不清?也许不是 - 但它肯定令人困惑并且需要更多时间来破译。我认为这是一个可怕的变化(无意冒犯你)。谢谢你的别名提示。 (8认同)
  • @PádraigBrady 我很感激你在维护 coreutils 方面所做的工作。但是更改 `ls` 的默认格式是一个错误。简单的解决方法是使新格式“选择加入”。发行版已经包含 `.bashrc` 文件,这些文件通常会调整 `ls` 和其他 coreutils 的行为,添加颜色等。这将是为需要它的人启用新格式的正确位置。 (7认同)
  • “用户可以通过将 -N 添加到他们的 ls 别名来恢复旧格式”如果他们想要这个输出,用户已经可以设置 QUOTING_STYLE=shell。更改默认值只会为发行版带来更多工作。 (6认同)
  • 我同意@Wyatt8740 - 这不是一个好主意。至少默认的`?` 替换是正式承认的 - 这只是离墙。您正在向文件名中*添加*字符,这些字符不在应该列出文件名的实用程序的输出中的文件名中。在我看来,对 shell-eval-safe 所说的文件名这样做是错误的。除非您稳健地执行此操作并在输出中引用任何可能的 shell 引用,否则您只是在用一种糟糕的罕见情况换取更糟糕的情况*并且*因此而扭曲您的输出。*请*尽可能做标准的事情。 (4认同)
  • 对于它的价值,我检查了 [POSIX 规范](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html) 并指出 *“如果输出到终端,格式是实现定义”*,因此此更改仍然符合标准。 (4认同)
  • pps - 根据您粘贴到的位置,转义甚至不一定有帮助。特别是粘贴到脚本或 GUI 应用程序中。 (3认同)
  • 请注意,复制粘贴在 `xterm` 中仍然不适用于使用 `touch $'Pa\u301draig'` 创建的文件,其中 `xterm` 将 `a\u301` 替换为 `\ue1`。`screen` 或 `luit` 也可以做一些字符集转换,这会破坏复制粘贴。 (3认同)
  • @StéphaneChazelas 不知道这一点。还有更多理由再次将其设为非默认值。 (3认同)
  • “建议”**添加**一个参数以**恢复**到旧的默认行为确实是一个坏主意。 (3认同)
  • 我很惊讶在这个答案的评论中看到如此消极。这种变化非常好,非常受欢迎。它本质上是一个安全修复程序,因此它是完全合理的,并且默认情况下会启用它。如果它破坏了您的任何东西,那么您的东西很可能首先是不安全的。 (3认同)
  • @mikeserv 哇,甚至不知道 `vdir` 是一回事。看起来完全像`ls -l`。同意这太公然违反预期规范是一件好事。简单应该是默认的,复杂是可选的,如果有的话。做一件事,并把它做好。 (2认同)
  • @Wyatt8740,@StéphaneChazelas 指出 xterm 使用标准化组合 (NFKC) 进行输出,这对于与 ls 中的此更改无关的剪切和粘贴是有问题的。事实上,对于这种情况,这个 ls 更改可以通过使用 `LC_ALL=C ls` 来引用这些文件(ps 在上面的例子中需要指定 4 个十六进制字符,即 `$'Pa\0301draig'`) (2认同)
  • “它只在输出到终端时发生,所以不会破坏脚本”——我想这很好,但无论如何没有人应该在脚本中解析 `ls` 的输出。不幸的是,这种做法太频繁了。 (2认同)
  • 把我算作这个 bug 的受影响用户,这个 bug 是由“ls”的*当前*开发人员故意引入的。 (2认同)