在 Mac 上,如何列出非当前目录的内容而不显示备份文件(以 ~ 结尾),最好使用 BSD 命令 ls?

在 Mac 上,如何列出非当前目录的内容而不显示备份文件(以 ~ 结尾),最好使用 BSD 命令 ls?

我的系统:

  • 操作系统:MacOS / Mac OS X (Mojave 10.14.5)
  • 操作系统核心:Darwin (18.6.0)
  • 内核:达尔文内核 / XNU (18.6.0 / xnu-4903.261.4~2/RELEASE_X86_64)
  • ls:版本未知,但man ls提供了 BSD 通用命令手册中的页面
  • 贝壳:
    • Bash:GNU bash,版本 5.0.7(1)-release (x86_64-apple-darwin18.5.0)
    • zsh:zsh 5.7.1(x86_64-apple-darwin18.2.0)

在 MacOS 中,在使用 bash 或 zsh 等 shell 的终端 CLI 中,我想使用 (BSD) 命令ls(或者可能是类似的常见且有用的工具)来列出当前工作目录以外的目录的内容,其中~显示除以波形符 ( ) 结尾的文件之外的所有文件。

排除最后一个规定,ls当非当前目录用作 的参数时,自然可以完成此任务lsls arg其中arg是非当前目录的绝对或相对路径(例如/absolute/path/to/directory~/path/from/home/to/directorypath/from/current/dir/to/directory)。

-d我知道如何使用文件名扩展(又名“globbing”)和选项(列出目录而不是其内容)来列出当前目录中的非备份内容,如下所示:(ls -d *[^~]ls -d *[!~])。我想要相同类型的结果,但对于非当前目录。

我几乎可以通过使用 来实现我想要的ls -d arg/*[^~],其中arg与上面描述的相同,但结果显示每个内容元素的路径(即感兴趣的目录中的每个文件和目录)。我想ls显示每个元素而不显示其路径,就像使用ls arg.

在 Linux 中,使用 GNU 命令,我可以使用不列出备份文件的选项来ls实现我想要的效果: 。虽然这是我想要的,但我想使用 MacOS 原生的工具(最好是 BSD )来实现这一目标。-Bls -B argls

注意:我不想使用grep(例如,ls arg | grep '.*[^~]$'),因为grep更改了输出的格式和颜色。

问题回顾:在 Mac 上,如何列出非当前目录的内容但不列出备份文件,最好使用ls

答案1

您可以ls在子 shell 中执行:

(cd arg; ls -d *[^~])

答案2

使用bash及其GLOBIGNOREshell 变量,以及 macOS 的basename

$ mkdir dir
$ touch dir/file{1,2}{,~}
$ ls -R
dir

./dir:
file1   file1~  file2   file2~
$ GLOBIGNORE=*~
$ ls -d dir/*
dir/file1       dir/file2
$ basename -a dir/*
file1
file2

设置GLOBIGNORE为 - 分隔模式列表:将使文件名完成忽略这些模式。

如果您使用其选项,macOS 中的实用basename程序将接受多个路径名-a,并将返回一个仅包含这些路径名的文件名部分的列表。

您显然可以使用您的模式,而不是使用GLOBIGNORE(它提供了一种更通用的方法来忽略某些文件名模式扩展)*[!~](请注意,它!否定 shell 中的字符类,同时^否定正则表达式中的字符类):

unset GLOBIGNORE
basename -a dir/*[!~]

...或者,您可以从 Homebrew 安装 GNU coreutils 并gls -B按照您在 Linux 系统上可能习惯的方式使用。

答案3

简洁的答案是使用子shell在非当前目录中执行命令:

(cd arg; ls -d *[^~])

但是为了创建一个适用于当前目录以及任何非当前目录的通用函数,我们可以将以下内容添加到.bashrc(或添加到bashrc_aliases_lsBSD,源自.bashrc):

alias ls='/bin/ls'
alias   l=''
unalias l
function l () { ( if [[ -n "$@" ]]; then cd "$@"; fi ; /bin/ls -d *[^~] ) }

如果我们违背上面提到的使用 BSD 的偏好,我们可以通过安装 GNU 核心实用程序(例如,via )并在(或在,来源为)中创建所需的别名(而不是使用上面的代码)来ls毫无问题地使用 GNU :brew install coreutils.bashrcbashrc_aliases_lsGNU.bashrc

alias ls='/usr/local/bin/gls'
alias l='/usr/local/bin/gls -B'

我自己当前的解决方案是使用这两种结构,并在需要时使用我调用的变量LS_TYPE和我调用的函数ls-switch(在 中定义bashrc_aliases,来源为.bashrc)在它们之间切换,该函数获取包含这两种结构的两个配置文件之一:

function ls-switch () {
    if [[ $LS_TYPE = "GNU" ]] ; then
        LS_TYPE="BSD"
        source ~/.config/bash/bashrc_aliases_lsBSD
    elif [[ $LS_TYPE = "BSD" ]] ; then
        LS_TYPE="GNU"
        source ~/.config/bash/bashrc_aliases_lsGNU
    fi
}

ls通过这种安排,和的默认行为是通过第一个定义和选择要获取哪个配置文件来l设置的,例如:.bashrcLS_TYPE

LS_TYPE="BSD"
source ~/.config/bash/bashrc_aliases_lsBSD

相关内容