![ls: Отображение имени каталога, если только одно соответствует шаблону](https://rvso.com/image/168781/ls%3A%20%D0%9E%D1%82%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%B8%D0%BC%D0%B5%D0%BD%D0%B8%20%D0%BA%D0%B0%D1%82%D0%B0%D0%BB%D0%BE%D0%B3%D0%B0%2C%20%D0%B5%D1%81%D0%BB%D0%B8%20%D1%82%D0%BE%D0%BB%D1%8C%D0%BA%D0%BE%20%D0%BE%D0%B4%D0%BD%D0%BE%20%D1%81%D0%BE%D0%BE%D1%82%D0%B2%D0%B5%D1%82%D1%81%D1%82%D0%B2%D1%83%D0%B5%D1%82%20%D1%88%D0%B0%D0%B1%D0%BB%D0%BE%D0%BD%D1%83.png)
При использовании ls
для отображения файлов, соответствующих шаблону, он отображает имена каталогов с содержимым, если есть несколько совпадений, но если есть только одно совпадение, он опускает имя каталога. Вот пример:
example % ls
bar barbados foo
example % ls b*
bar:
1 2
barbados:
1 2
example % ls f*
1 2
В этом примере запрос всех файлов, начинающихся с, b*
соответствует двум каталогам, а в выводе отображаются имена обоих каталогов и их содержимое.
При запросе f*
вывод показывает содержимое единственного соответствующего каталога, но опускает имя каталога.
Как настроить ls
отображение имени соответствующего каталога в случае, если он соответствует только одному каталогу?
решение1
Возможным решением может стать функция-обертка:
dls() {
if [ "$#" -eq 1 ] && [ -d "$1" ]; then
printf '%s:\n' "$1"
fi
ls -- "$@"
}
- Приведенная выше функция не принимает никакие параметры, передаваемые в качестве аргументов.
- Он просто проверяет:
- есть только один аргумент
- аргумент — это каталог
Если эти два условия выполняются, выведите имя каталога перед перечислением его содержимого.
% dls f*
foo:
1 2
В некоторых printf
реализациях можно заменить %s
на %q
, чтобы имя каталога было заключено в кавычки аналогично тому, как ls
это делают последние версии GNU, когда оно содержит пробелы или другие специальные символы.
решение2
Используя ваши примеры, когда вы выполняете ls b*
, оболочка расширяет b*
в bar barbados
, так что вы фактически запускаете ls bar barbados
. Когда ls
имеет несколько аргументов, если какой-либо из них является каталогом, он печатает имя, за которым следует список файлов в каталоге.
Когда вы выполняете ls f*
, то shell расширяет f*
в foo
, так что вы фактически запускаете ls foo
. Когда ls
имеет один аргумент, если этот аргумент является каталогом, выводит список файлов в каталоге (без имени каталога).
Нет того, что я бы назвал "хорошим" способом сделать ls
то, что вы хотите (по крайней мере, я о таком не знаю, кто-то другой может знать лучше). Один "менее хороший" способ - включить дополнительный аргумент, который, как вы знаете, никогда не будет существовать, а затем отфильтровать вывод ошибок, связанных с этим несуществующим файлом. Я отмечу для протокола, что парсинг вывода ls
- плохая идея, но я дам вам это на всякий случай:
$ function dls() {
if [[ $# -eq 0 ]]; then
ls
else
ls ${@} this-file-does-not-exist-anywhere 2> >(grep -v this-file-does-not-exist-anywhere)
fi
}
$ dls
foo
$ dls f*
foo:
1 2
Подобные действия могут иметь непредвиденные последствия (например, вы не сможете перенаправлять стандартные сообщения об ошибках, как обычно).
решение3
Используйте -al
параметр, который большинство людей используют каждый раз. ls
не будет делать этого тогда, пока вы не добавите завершающий слеш к имени каталога. Другой параметр - это -d
, он не будет спускаться никаким образом, тогда.
Если вы хотите, чтобы он был постоянным, поместите следующее в .bashrc
свой домашний каталог:
alias lsd='ls -d' ;
Эту команду вы сможете использовать lsd
в будущем.