Aka*_*3di 1 ls wildcards case-sensitivity
因此,我一直在玩弄文件系统,并想知道如何列出/etc名称中仅包含大写字母的文件。我命令
ls *[A-Z]*
Run Code Online (Sandbox Code Playgroud)
但是控制台也显示包含较低字符的文件。我只想使用ls命令。控制台程序语言环境是否相关?
根本原因是什么?
[A-Z]不代表大写。它表示来自Ato 的字母Z,其中可能包括小写字母。通常你应该使用它[[:upper:]]。(即使没有extglob.,这也适用于 Bash 。)
[A-Z]匹配哪些字符取决于您的语言环境。您已经阐明,您希望在任何地方显示至少包含一个大写字符的所有文件名——不仅是完全由大写字母组成的文件名——而且当您使用 时ls *[A-Z]*,您会得到一些没有任何大写字符的文件名-其中的大小写字符。
当您的语言环境的字典顺序中包含大写和小写字母(例如,AaBbCcDd...)时,就会发生这种情况。尽管您可以设置其他语言环境(例如,LC_ALL=C),但最好的解决方案通常是编写一个专门匹配大写字母的模式。
哪些字符是大写字母也可能因语言环境而异,但大概如果某些内容在您的语言环境中是大写字母,那么您想要包含它。所以这可能是优点[[:upper:]]而不是缺点。
[[:upper:]]来代替。大多数 Bourne 风格的 shell,例如 Bash,都支持 globs 中的 POSIX 字符类。此命令将列出/etc名称中至少有一个大写字母的条目:
ls -d /etc/*[[:upper:]]*
Run Code Online (Sandbox Code Playgroud)
您获得的某些条目可能是目录。如果您想显示它们的内容而不仅仅是列出目录,那么您可以删除该-d标志。您可能还想--在模式之前放置一个标志,以防您有以/etc开头的条目-。不过,您可能不会。(在脚本中,您通常希望在--此处使用。)
这不会显示以 开头的条目.。通常你不想展示它们。如果您确实需要它们,大多数 shell 允许您编写一个也匹配它们的单个 glob,或者将 globbing 配置为默认包含它们。.在 Bash 中自动包含前导条目的选项是dotglob,可以使用shopt -s dotglob. 对于其他外壳,请参阅
。或者您可以简单地为它们编写第二个 glob:
ls -d /etc/*[[:upper:]]* /etc/.*[[:upper:]]*
Run Code Online (Sandbox Code Playgroud)
最流行的 Bourne 风格的 shell 支持大括号扩展,所以你可以用更少的重复写得更紧凑:
ls -d /etc/{,.}*[[:upper:]]*
Run Code Online (Sandbox Code Playgroud)
在包括 Bash 在内的大多数 shell 中,当您编写两个单独的 glob 时,当其中一个不展开时,您将收到一条错误消息——因为大多数 shell 中的默认行为是不展开地传递它。但ls仍会显示与另一个匹配的条目。但是正如 Stéphane Chazelas 指出的那样,在包括非常流行的 Zsh 在内的一些 shell 中,整个命令失败并且ls永远不会运行。如果您以交互方式使用 shell,这并不是真正有害,因为您可以修改命令再次运行它,但是这种结构不适合可移植脚本。如果您设置了failglobshell 选项,Bash 也会以这种方式运行。
在 Bash 中,您不需要启用扩展 globbing 即可在 glob 模式中使用 POSIX 字符类。在我使用 Bash 4.3.48 的系统上:
ek@Io:~$ shopt extglob
extglob off
ek@Io:~$ ls -d /etc/*[[:upper:]]*
/etc/ConsoleKit /etc/LatexMk /etc/ODBCDataSources /etc/UPower
/etc/ImageMagick-6 /etc/NetworkManager /etc/rcS.d /etc/X11
Run Code Online (Sandbox Code Playgroud)
你怎么做,如果你想匹配文件名包含扩展的需要为通配符是唯一的大写字母。然后你会使用+([[:upper:]])or *([[:upper:]]),那些是扩展的glob。
如果您正在使用 Bash,请参阅本文、本指南、GNU Bash 手册中的3.5.8.1 模式匹配以了解详细信息。另请参阅Stéphane Chazelas 的回答。