Как на Mac вывести список содержимого не текущего каталога, не отображая файлы резервных копий (заканчивающиеся на ~), желательно с помощью команды BSD ls?

Как на Mac вывести список содержимого не текущего каталога, не отображая файлы резервных копий (заканчивающиеся на ~), желательно с помощью команды BSD ls?

Моя система:

  • ОС: MacOS / Mac OS X (Mojave 10.14.5)
  • Ядро ОС: Darwin (18.6.0)
  • Ядро: Darwin Kernel / XNU (18.6.0 / xnu-4903.261.4~2/RELEASE_X86_64)
  • ls: версия неизвестна, но man lsвыдает страницу из BSD General Commands Manual
  • Ракушки:
    • Bash: GNU bash, версия 5.0.7(1)-релиз (x86_64-apple-darwin18.5.0)
    • Zsh: zsh 5.7.1 (x86_64-apple-darwin18.2.0)

В MacOS в терминальном CLI с использованием оболочки, такой как bash или zsh, я хотел бы использовать команду (BSD) (или, возможно, аналогичный распространенный и полезный инструмент) для вывода списка содержимого каталога, отличного от текущего рабочего каталога, где отображаются lsвсе файлы, за исключением тех, которые заканчиваются на тильду ( ).~

За исключением последнего условия, lsэта задача естественным образом выполняется, когда не текущий каталог используется в качестве аргумента для ls: ls argгде arg— абсолютный или относительный путь к не текущему каталогу (например /absolute/path/to/directory, ~/path/from/home/to/directory, или path/from/current/dir/to/directory).

Я знаю, как перечислить содержимое, не являющееся резервной копией, в текущем каталоге, используя расширение имени файла (также известное как «подстановка») и опцию -d(перечислить каталоги, а не их содержимое), например: ls -d *[^~](или ls -d *[!~]). Мне нужны такие же результаты, но для не текущего каталога.

Я почти могу добиться того, чего хочу, используя ls -d arg/*[^~], где argто же самое, что описано выше, но результаты показывают путь к каждому элементу контента (т. е. каждому файлу и каталогу в интересующем каталоге). Я хочу lsотобразить каждый элемент без пути к нему, как это делается с ls arg.

В Linux, используя команду GNU ls, я могу добиться именно того, чего хочу, используя -Bопцию не выводить список файлов резервных копий: ls -B arg. Хотя это то, что мне нужно, я хотел бы добиться этого с помощью инструментов, встроенных в MacOS, предпочтительно BSD ls.

Примечание: Я не хочу использовать grep(например, ls arg | grep '.*[^~]$'), так как grepэто изменяет форматирование и окраску вывода.

Повтор вопроса: как на Mac вывести список содержимого не текущего каталога, но не файлов резервных копий, желательно с помощью ls?

решение1

Вы можете выполнить lsв подоболочке:

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

решение2

Использование bashи его GLOBIGNOREпеременной оболочки вместе с 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список :шаблонов с разделителями, то при завершении имени файла эти шаблоны будут игнорироваться.

Утилита basenameв macOS принимает более одного имени пути, если вы используете ее -aопцию, и возвращает список, состоящий только из частей имен файлов этих путей.

Вместо использования GLOBIGNORE(что обеспечивает более общий способ игнорировать определенные расширения шаблонов имен файлов) вы, очевидно, можете использовать свой шаблон *[!~](обратите внимание, что !он отрицает класс символов в оболочке, в то время как ^отрицает класс символов в регулярных выражениях):

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

... или вы можете просто установить GNU coreutils из Homebrew и использовать его gls -Bтак, как вы привыкли в системах Linux.

решение3

Короткий ответ — использовать подоболочку для выполнения команды в нетекущем каталоге:

(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 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

Связанный контент