在 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

相關內容