在目录中创建以下文件。
$ touch .a .b a b A B ???
Run Code Online (Sandbox Code Playgroud)
我的默认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 ???
Run Code Online (Sandbox Code Playgroud)
$ 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 ???
Run Code Online (Sandbox Code Playgroud)
不幸的是,这使得排序顺序区分大小写,即AandB在aand之前b。有没有办法先打印点文件,同时保持不区分大小写(A并a在B和之前b)?
到目前为止,没有一个答案可以完全复制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
Run Code Online (Sandbox Code Playgroud)
/usr/share/i18n/locales/iso14651_t1包含copy "iso14651_t1_common". 最后,/usr/share/i18n/locales/iso14651_t1_common包含
<U002E> IGNORE;IGNORE;IGNORE;<U002E> # 47 .
Run Code Online (Sandbox Code Playgroud)
我删除了这一行,运行sudo locale-gen,然后重新启动了我的电脑。不幸的是,这没有任何改变。
bea*_*dip 17
OP与编辑非常接近/usr/share/i18n/locales/iso14651_t1_common,但诀窍是不要删除该行
<U002E> IGNORE;IGNORE;IGNORE;<U002E> # 47 .
Run Code Online (Sandbox Code Playgroud)
而是将其修改为
<U002E> <RES-1>;IGNORE;IGNORE;<U002E> # 47 .
Run Code Online (Sandbox Code Playgroud)
这些IGNORE语句指定在<U002E>按字母顺序排列单词时将忽略句号(又名句点或字符)。要使您的点文件排在第一位,请更改IGNORE为排在所有其他字符之前的整理符号。整理符号由类似的行定义
collating-symbol <something-inside-angle-brackets>
Run Code Online (Sandbox Code Playgroud)
它们是按线的外观排序的
<something-inside-angle-brackets>
Run Code Online (Sandbox Code Playgroud)
在我的 副本中iso14651_t1_common,第一个排序符号是<RES-1>,它出现在第 3458 行。如果您的文件不同,请使用最先排序的排序符号。
<U002E>有 3 个IGNORE语句,因为如果出现关系,可以多次比较字母。要理解这一点,请考虑小写a和大写A(它们是实际比较四次的一组字符的一部分):
<U0061> <a>;<BAS>;<MIN>;IGNORE # 198 a
<U0041> <a>;<BAS>;<CAP>;IGNORE # 517 A
Run Code Online (Sandbox Code Playgroud)
多轮比较允许将以“a”和“A”开头的文件组合在一起,因为<a>在第一遍期间比较两者,下一个字母确定排序。如果以下所有字母都相同(例如a.txt和A.txt),则第三遍将放在a.txt最前面,因为小写字母的整理符号<MIN>出现在第 3467 行,在大写字母的整理符号<CAP>(第 3488 行)之前。
如果您希望每次程序使用 订购信件时都首先出现句点LC_COLLATE,您可以iso14651_t1_common按上述方式进行修改并重建您的位置文件。但是,如果你想使这一变化只对ls和无根的访问,可以将原有的语言文件修改之前复制到另一个目录。
我的默认语言环境是en_US,所以我复制en_US,iso14651_t1以及iso14651_t1_common到$HOME/path/to/new/locales。在那里我进行了上述更改并重iso14651_t1_common命名en_US为en_DOTFILE. 接下来我编译了 en_DOTFILE 语言环境
localedef -i en_DOTFILE -f UTF-8 -vc $HOME/path/to/new/locales/en_DOTFILE.UTF-8
Run Code Online (Sandbox Code Playgroud)
要替换默认ls排序,请创建一个名为 的 BASH 脚本ls:
#!/bin/bash
LOCPATH=$HOME/path/to/new/locales LANG=en_DOTFILE.UTF-8 ls "$@"
Run Code Online (Sandbox Code Playgroud)
将其保存/usr/bin在路径上出现之前的某个位置,并使用chmod +x ls.
Ste*_*itt 11
您可以改用 shell 的排序顺序(这可能不涉及语言环境的排序顺序;bash, AT&T ksh, yash,tcsh并zsh给出预期的结果,mksh而dash不是。fish似乎给出了不区分大小写的顺序,但当存在非 ASCII 时给出不同的结果人物):
ls -dUl -- .* *
Run Code Online (Sandbox Code Playgroud)
这给出ls了要列出的文件(和目录)的明确列表,并停用ls的排序(-U,这是一个 GNU 扩展)。
有一些注意事项,具体取决于您使用的外壳。
zsh,nomatch如果目录不包含隐藏和非隐藏文件,默认选项将导致命令失败;您可以禁用nomatch以避免这种情况,但最好改为这样做set -o cshnullglob(并且只有在没有任何 globs 匹配(t)csh或早期的 Unix shell 时,命令才会失败)。zsh,pdksh及其派生 and fish,.*的扩展不包括.and ..,所以这匹配ls -Al。与其他壳.和..包括这样它匹配ls -al。在后一种情况下,您需要更改通配模式以排除.和..( ls -dUl -- ..?* .[!.]* *)。fish, (t)cshor zsh,如果任何通配模式不匹配任何内容,ls将产生错误消息;您可以通过设置nullglob选项(bash或zsh至少)或重定向stderr到/dev/null( ls -dUl -- ..?* .[!.]* * 2>/dev/null)来避免这种情况。如果您使用nullglob,请注意可能导致的令人惊讶的行为(请参阅Shell 吃 `?` 字符)。fish行为与bashwithnomatch除了交互时,将为每个没有匹配的 glob 发出警告消息。(感谢Stéphane Chazelas的所有反馈!)