Моя система:
- ОС: 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