我的系统:
- 操作系统: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
当非当前目录用作 的参数时,自然可以完成此任务ls
:ls arg
其中arg
是非当前目录的绝对或相对路径(例如/absolute/path/to/directory
、~/path/from/home/to/directory
或path/from/current/dir/to/directory
)。
-d
我知道如何使用文件名扩展(又名“globbing”)和选项(列出目录而不是其内容)来列出当前目录中的非备份内容,如下所示:(ls -d *[^~]
或ls -d *[!~]
)。我想要相同类型的结果,但对于非当前目录。
我几乎可以通过使用 来实现我想要的ls -d arg/*[^~]
,其中arg
与上面描述的相同,但结果显示每个内容元素的路径(即感兴趣的目录中的每个文件和目录)。我想ls
显示每个元素而不显示其路径,就像使用ls arg
.
在 Linux 中,使用 GNU 命令,我可以使用不列出备份文件的选项来ls
实现我想要的效果: 。虽然这是我想要的,但我想使用 MacOS 原生的工具(最好是 BSD )来实现这一目标。-B
ls -B arg
ls
注意:我不想使用grep
(例如,ls arg | grep '.*[^~]$'
),因为grep
更改了输出的格式和颜色。
问题回顾:在 Mac 上,如何列出非当前目录的内容但不列出备份文件,最好使用ls
?
答案1
您可以ls
在子 shell 中执行:
(cd arg; ls -d *[^~])
答案2
使用bash
及其GLOBIGNORE
shell 变量,以及 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
.bashrc
bashrc_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
设置的,例如:.bashrc
LS_TYPE
LS_TYPE="BSD"
source ~/.config/bash/bashrc_aliases_lsBSD