如何让 ls 首先对下划线字符进行排序?

Tom*_*ger 23 ls sort locale

如果我想将文件和目录与同一级别的其他文件和目录分开,我喜欢能够使用下划线前缀命名文件和目录。例如,在 Windows 和 Mac 上,为文件添加下划线前缀会将其排在顶部,位于以字母数字字符开头的文件前面。

我的谷歌搜索结果表明它与 LC_COLLATE 和我当前的语言环境(en_US)有关。没关系,虽然我真的不明白为什么 en_US 没有按预期排序。

基于ICU Collat​​e 演示站点,将 locale 设置为 en_US_POSIX 显然具有我正在寻找的排序顺序(您必须编辑示例数据并添加一些下划线以对其进行测试)。但我真的不知道如何在我的 Linux shell 中应用它。

理想情况下,我希望能够在我的 bash 配置中设置一些东西,以便 ls 总是首先对下划线进行排序。我该怎么做呢?

Gil*_*il' 17

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

$ LC_COLLATE=C ls    
BAR  FOO  _score  _under  hello  world
$ LC_COLLATE=en_US ls                    
BAR  FOO  hello  _score  _under  world
Run Code Online (Sandbox Code Playgroud)

区域设置LC_MESSAGES(错误消息的语言)、LC_CTYPE(字符集)和LC_TIME(日期和时间格式)非常有用。LC_COLLATE并且LC_NUMERIC通常比它们的价值更麻烦,我不建议设置它们。正确的字典排序比LC_COLLATE预期的要复杂,当您在正则表达式中使用字符范围时,它可能会导致各种奇怪的行为。LC_NUMERIC主要是装饰性的,除非出现可怕的错误,因为某些程序生成了一个小数点分隔符而不是..

  • 有什么办法让下划线出现在大写字母之前吗? (2认同)
  • @TomAuger 是的,`VAR=value cmd` 仅在 `cmd` 的环境中将 `VAR` 设置为 `value`,并且不会在运行它的 shell 中触及该值(或没有值)。要使下划线出现在大写之前,您需要定义自己的区域设置。这是可能的,但使用起来很尴尬,因为至少在 Linux 下,标准库只在 `/usr/lib/locale` 中查找语言环境定义——没有 `~/.locale` 或环境变量可以放置你的 ` en_tom` 设置。 (2认同)
  • @IulianOnofrei 它来自[C 编程语言](https://en.wikipedia.org/wiki/C_(programming_language)) 中的默认语言环境。其作用是根据字符的编码以简单的方式对字符进行分类和排序,并使用默认的英语约定来表示消息、数字和时间。 (2认同)

Mik*_*kel 6

如果您无法ls按照您想要的方式进行排序,请尝试外壳扩展。

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

ls -lf _* [!_]*
Run Code Online (Sandbox Code Playgroud)

假设你有文件

_a a _b b _c c
Run Code Online (Sandbox Code Playgroud)

这就像跑步

ls -lf _a _b _c a b c
Run Code Online (Sandbox Code Playgroud)

解释:

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

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

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

更多信息:bash 文件名扩展

如果当前目录中有目录,您需要像这样运行命令以避免 ls 列出目录中的文件:

ls -lfd _* [!_]*
Run Code Online (Sandbox Code Playgroud)

  • 顺便说一句,DOS/Windows/OSX 并没有真正将下划线放在其他任何东西之前:它们不区分大小写,将下划线放在字母之前,但其他一些标点字符放在下划线之前或之后。使用 `_` 使文件首先出现是特定于操作系统的技巧;这个 hack 的 unix 版本是以大写字母开头的文件名:默认的 unix 约定是在文件名中只使用小写字母。 (7认同)
  • 或零;例如`00README`。 (4认同)