如何使“ls”首先显示点文件,同时保持不区分大小写?

如何使“ls”首先显示点文件,同时保持不区分大小写?

在目录中创建以下文件。

$ touch .a .b a b A B 你好嗎

我的默认ls顺序忽略了前导点的存在,将它们与其他文件混合在一起。

$ ls -Al
total 0
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 a
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 .a
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 A
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 b
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 .b
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 B
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:06 你好嗎

改变 LC_COLLATE将点文件放在第一位。

$ LC_COLLATE=C ls -Al
total 0
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 .a
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 .b
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 A
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 B
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 a
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:03 b
-rw-r--r-- 1 sparhawk sparhawk 0 Jun  8 17:06 你好嗎

不幸的是,这使得排序顺序区分大小写,即AandB位于aand之前b。有没有办法先打印点文件,同时保持不区分大小写(AaBand之前b)?

编辑:尝试修改 LC_COLLATE

到目前为止,没有一个答案能够完全复制 easy 的功能ls。可以想象,我可以将其中一些包装在一个函数中,但这必须包含一些详细的代码(例如)如何在没有参数的情况下工作与提供目录作为参数。或者如何处理显式-d标志。

或者,我想也许有更好的LC_COLLATE选择。但是,我似乎无法做到这一点。我目前正在使用LC_COLLATE="en_AU.UTF-8".我检查了/usr/share/i18n/locales/en_AU(尽管我不确定这是否是正确的文件,因为我看不到任何对 的引用UTF-8);我发现了以下内容。

LC_COLLATE
copy "iso14651_t1"
END LC_COLLATE

/usr/share/i18n/locales/iso14651_t1包含copy "iso14651_t1_common".最后,/usr/share/i18n/locales/iso14651_t1_common包含

 <U002E> IGNORE;IGNORE;IGNORE;<U002E> # 47 .

我删除了这一行,运行sudo locale-gen并重新启动了我的计算机。不幸的是,这并没有改变什么。

答案1

OP与剪辑非常接近/usr/share/i18n/locales/iso14651_t1_common,但诀窍是不要删除线

<U002E> IGNORE;IGNORE;IGNORE;<U002E> # 47 .

而是将其修改为

<U002E> <RES-1>;IGNORE;IGNORE;<U002E> # 47 .

为什么这有效

这些语句指定按字母顺序对单词进行排序时将忽略IGNORE句号(也称为句点或字符)。<U002E>要使点文件排在第一位,请更改IGNORE为位于所有其他字符之前的整理符号。整理符号由类似以下的行定义

collating-symbol <something-inside-angle-brackets>

它们按线条的外观排序

<something-inside-angle-brackets>

在我的 副本中iso14651_t1_common,第一位整理符号是<RES-1>,它出现在第 3458 行。如果您的文件不同,请使用最先排序的整理符号。

有关使用 LC_COLLATE 进行字符排序的详细信息

<U002E>具有三个IGNORE语句,因为在平局的情况下可以多次比较字母。要理解这一点,请考虑小写a和大写A(它们是实际比较四次的一组字符的一部分):

<U0061> <a>;<BAS>;<MIN>;IGNORE # 198 a
<U0041> <a>;<BAS>;<CAP>;IGNORE # 517 A

进行多轮比较允许以“a”和“A”开头的文件分组在一起,因为两者都<a>在第一次传递期间进行比较,下一个字母确定顺序。如果后面的所有字母都相同(例如a.txtA.txt),则第三遍将放在第一位a.txt,因为小写字母的整理符号<MIN>出现在第 3467 行,位于大写字母的整理符号<CAP>(第 3488 行)之前。

实施此更改

如果您希望经期先出现每次程序使用 来排序字母LC_COLLATE,您可以iso14651_t1_common按照上述方式进行修改并重建您的位置文件。但如果你想做出这样的改变仅有的无论ls是否具有 root 访问权限,您都可以在修改原始语言环境文件之前将其复制到另一个目录。

我做了什么

我的默认区域设置是 en_US,因此我将en_USiso14651_t1和复制iso14651_t1_common$HOME/path/to/new/locales。在那里我进行了上述更改iso14651_t1_common并重命名en_USen_DOTFILE.接下来我编译了 en_DOTFILE 语言环境

localedef -i en_DOTFILE -f UTF-8 -vc $HOME/path/to/new/locales/en_DOTFILE.UTF-8

要替换默认ls顺序,请创建一个名为的 BASH 脚本ls

#!/bin/bash
LOCPATH=$HOME/path/to/new/locales LANG=en_DOTFILE.UTF-8 ls "$@"

将其保存在路径中之前出现的某个位置/usr/bin,并使其可执行chmod +x ls

答案2

您可以使用 shell 的排序顺序(可能不涉及语言环境的排序顺序;bash、 AT&T kshyashtcshzsh给出预期的结果,mkshdash不会。fish似乎给出了不区分大小写的顺序,但当存在非 ASCII 时给出了不同的结果人物):

ls -dUl -- .* *

这给出了ls要列出的文件(和目录)的明确列表,并停用 的ls排序(-U,它是 GNU 扩展)。

有一些注意事项,具体取决于您使用的 shell。

  • 使用 时,如果目录不包含隐藏文件和非隐藏文件,则zsh默认选项将导致命令失败;nomatch您可以禁用nomatch以避免这种情况,但更好的做法是set -o cshnullglob改为这样做(并且仅当没有任何全局匹配时,该命令才会失败,就像在(t)csh或早期的 Unix shell 中一样)。
  • 由于zsh,pdksh及其导数 and fish,.*的展开式不包括.and ..,所以这匹配ls -Al。与其他外壳并列在一起,因此它.匹配。在后一种情况下,您需要更改通配模式以排除和( )。..ls -al...ls -dUl -- ..?* .[!.]* *
  • 除了fish,(t)csh或 之外zsh,如果任何通配模式与任何内容都不匹配,ls将产生错误消息;您可以通过设置nullglob选项(在bashzsh至少)或重定向stderr/dev/nullls -dUl -- ..?* .[!.]* * 2>/dev/null)来避免这种情况。如果您使用nullglob,请注意可能导致的令人惊讶的行为(请参阅shell 吃 '?' 字符)。fish其行为与bashwith类似nomatch,只是在交互时,将为每个不匹配的 glob 发出警告消息。

(感谢斯蒂芬·查泽拉斯以获得所有反馈!)

答案3

您可以简单地使用两个单独的ls命令:

$ ls -dl ..?* .[^.]* 2>/dev/null ; ls -dl *
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 .a
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 .b
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 a
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 A
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 b
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 B
-rw-r--r--. 1 sparhawk sparhawk 0  8 Jun  09:29 你好嗎

与迄今为止的其他答案不同,此方法首先显示点文件,避免.和条目,然后按 字母顺序..显示其余条目。ls

@StephenKitt 的答案可能会得到改进,以达到相同的结果:

$ ls -dUl ..?* .[^.]* * 2>/dev/null

答案4

你可以玩LS命令选项。尝试这个:

# ls -laXr

在哪里:

-l     use a long listing format
-a, --all
              do not ignore entries starting with .
-X     sort alphabetically by entry extension
-r, --reverse
              reverse order while sorting

相关内容