如何使ls先排序下划线字符?


20

我希望能够使用下划线前缀来命名文件和目录,因为这是我想与同一级别的其他文件和目录分开的原因。例如,在Windows和Mac上,在文件前加下划线前缀会将其排在顶部,并以字母数字字符开头。

我的谷歌搜索发现它与LC_COLLATE和当前的语言环境(en_US)有关。很好,尽管我真的不明白为什么en_US不能按预期排序。

基于ICU Collat​​e演示站点,将语言环境设置为en_US_POSIX肯定符合我要查找的排序顺序(您必须编辑示例数据并添加一些下划线进行测试)。但是我真的没有看到如何在我的Linux shell中应用它。

理想情况下,我希望能够在我的bash配置中进行设置,以便ls始终首先对下划线进行排序。我将如何去做呢?


我无法使用带有默认值的ICU Collat​​e或通过“获取语言环境的规则”与en_US_POSIX.txt进行复制。您能解释一下您使用的设置吗?
Mikel 2012年


@Mikel使用上面提供的链接,在测试数据中添加一些下划线,然后提交以查看排序结果。
Tom Auger 2012年

这正是我所做的,并且以下划线开头的字符串在中间而不是在开头进行排序,就好像下划线不在那里。
Mikel 2012年

1
一个涉及实际更改排序规则定义的相关问题是unix.stackexchange.com/questions/421908
JdeBP

Answers:


5

如果您无法ls按照自己的方式进行排序,请尝试shell扩展。

您可以使用文件名模式来运行lsShell已排序的文件列表,从而绕过ls使用的方法。

ls -lf _* [!_]*

假设您有文件

_a a _b b _c c

这就像跑步

ls -lf _a _b _c a b c

说明:

_* 是一个shell模式,匹配以下划线开头的任何文件名,并按字母顺序扩展。

[!_]*匹配任何以下划线开头且按字母顺序扩展的文件名。

-f告诉ls排序,因为shell已经做了。

更多信息:bash文件名扩展

如果当前目录中有目录,则您将需要运行以下命令,以避免ls在目录中列出文件:

ls -lfd _* [!_]*

7
顺便说一句,DOS / Windows / OSX并没有在其他任何东西前加下划线:它们在字母前加上下划线,不区分大小写,但其他一些标点符号在下划线之前或之后。使用_使文件出现第一种是特定于操作系统的黑客; 而这种hack的unix版本是以大写字母开头的文件名:默认的unix约定是在文件名中仅使用小写字母。
吉尔(Gilles)'所以

4
或零;例如00README
mattdm 2012年

1
@Gilles +1是在重要文件上使用大写字母使其首位的UNIX最佳实践。归根结底,如果这是约定俗成的话,那么最好是我简单地采用它,而不是试图迫使Unix像其他操作系统那样行事,所以我可以使用为Mac或Windows开发的约定。感谢您的提示。
Tom Auger 2012年

1
@TomAuger -f告诉ls自己不要进行排序,因此它将按照传递的顺序显示其参数。每个shell通配符扩展的结果,_*并且[!_]*是按字典顺序排序的列表。
吉尔(Gilles)'所以

1
@TomAuger 当shell生成参数时,将对ls它们进行排序(分为两组:以开头的_,然后是其他)。跑去echo ls -lf _* [!_]*看看会发生什么。该-f标志指示ls不要进行任何排序。
吉尔斯(Gillles)“所以-别再邪恶了”

16

如果您不希望混合使用小写字母和大写字母,请将您的语言环境设置为C,这将按数字顺序输入字符。_介于大写和小写之间。

$ LC_COLLATE=C ls    
BAR  FOO  _score  _under  hello  world
$ LC_COLLATE=en_US ls                    
BAR  FOO  hello  _score  _under  world

语言环境设置LC_MESSAGES(错误消息的语言),LC_CTYPE(字符集)和LC_TIME(日期和时间格式)非常有用。LC_COLLATE并且LC_NUMERIC通常比他们值得的麻烦更多,我不建议设置它们。正确的词典编排排序要比LC_COLLATE指定的要复杂得多,当您在正则表达式中使用字符范围时,它可能导致各种奇怪的行为。LC_NUMERIC基本上是装饰性的,除非由于某些程序产生的数字带有除以外的小数点分隔符而导致严重错误时除外.


+1非常有趣。因此,使用这种形式,您只是为那一个ls实例临时设置了环境变量LC_COLLATE吗?那正确吗?
Tom Auger 2012年

1
有什么方法可以使下划线出现在大写字母之前?
Tom Auger 2012年

1
@TomAuger是的,仅在运行它的外壳程序中的环境下VAR=value cmd设置VAR为并且不接触其值(或没有值)。要使下划线出现在大写字母之前,您需要定义自己的语言环境设置。这是可行的,但使用起来很麻烦,因为至少在Linux下,标准库仅在以下位置查找语言环境定义- 可以在其中放置环境变量或环境变量。valuecmd/usr/lib/locale~/.localeen_tom
吉尔(Gilles)“所以

@TomAuger如果这仅与ls命令有关,请遵循Mikel的建议
吉尔(Gilles)'所以


-4

添加-f开关(不进行排序)使它对我显示出这种方式。

man ls

[root@dusknoir ~/java/test]# ls -fl
total 0
-rw-r--r--  1 root  wheel  0 Jun  1 13:27 _1
-rw-r--r--  1 root  wheel  0 Jun  1 13:27 _2
-rw-r--r--  1 root  wheel  0 Jun  1 13:27 _3
-rw-r--r--  1 root  wheel  0 Jun  1 13:27 1
-rw-r--r--  1 root  wheel  0 Jun  1 13:27 2
-rw-r--r--  1 root  wheel  0 Jun  1 13:27 3

6
只是因为那是它们在文件系统中的存储方式。
伊格纳西奥·巴斯克斯

3
抱歉,这个答案是完全错误的。测试:touch 3 1 _1 _3 2 _2 && ls -fl输出2 . 1 3 _2 _3 .. _1
Marco
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.