Как использовать locate для поиска только папок

3065
shrx

В системе UNIX «locate» ищет в базе данных файлы с выбранным именем или файлы в папке с выбранным именем. Как я могу использовать locate для вывода только папок, а не файлов?

3
Смотрите также [тот же вопрос на unix.stackexchange.com] (http://unix.stackexchange.com/q/192739) sch 9 лет назад 0

7 ответов на вопрос

5
Frank M

На самом деле, locateесть то, что нужно, если вы используете --regexpопцию, и вы не против, чтобы она выплевывала файлы с тем же именем, что и каталоги, которые вы ищете. Маркер положения "конец строки" выполняет свою работу:

locate -r '/dirname$' 

locateтакже поддерживает, --ignore-caseесли это то, что вы хотите.

Чтобы найти все каталоги, `locate -r '/[^\.]*$'`. Mateen Ulhaq 6 лет назад 0
Подход Матина не фильтрует каталоги. Он возвращает все в базе данных. ОП искал конкретный каталог и, похоже, знает имя нужного ему каталога. Frank M 6 лет назад 0
3
Scott C Wilson

Почему бы не использовать команду поиска?

find . -name YOUR_SEARCH_NAME -type d 
найти быстрее, и мне не нужно, чтобы быть постоянно обновленным для моей цели. shrx 12 лет назад 4
2
Der Hochstapler

locateСам не могу сделать это для вас. Таким образом, UNIX способ сделать это - отфильтровать вывод locate:

locate --null something | xargs -r0 sh -c 'for i do [ -d "$i" ] && printf "%s\n" "$i"; done' sh {} + 
Эта команда только что перезагрузила мою машину (у меня был файл `/ tmp / что-то $ (reboot)`). sch 9 лет назад 5
@ щ это вау Der Hochstapler 9 лет назад 2
Правильный путь - что-то вроде `найти --null что-то | xargs -r0 sh -c 'для меня [-d "$ i"] && printf "% s \ n" "$ i"; сделано 'ш {} + `. `{}` никогда не следует встраивать в код оболочки, это так же плохо, как использовать `eval` с произвольными данными (отсюда и downvote). sch 9 лет назад 0
Обратите внимание, что `[-d` также возвращает true для символических ссылок на каталоги. Не обязательно плохо, просто стоит отметить, поскольку он отличается, например, от `find -type d`. sch 9 лет назад 0
@sch: Ну, если вы не понимаете последствий и если у вас есть привычка иметь файлы с именем $ (reboot) на вашем компьютере, возможно, вам не следует запускать команды, которые вы найдете в Интернете, с помощью `sudo `; D Но, спасибо за предоставление лучшей версии, не стесняйтесь редактировать или публиковать ее как ответ, чтобы она не терялась в комментариях. Der Hochstapler 9 лет назад 1
Системы Unix являются многопользовательскими, и / tmp доступен для записи во всем мире (и даже в однопользовательских системах вы или сетевая служба могут быть обмануты в создании файлов с такими именами). Внедрение этого `{}` подобного типа является ошибкой, легко обновляемой до уязвимости безопасности. ИМО, на общедоступных сайтах вопросов и ответов, мы должны хотя бы указать на ограничения. Не стесняйтесь включать этот код в свой ответ. Я вообще не участвую в [SU], я только что получил ссылку по [unix.SE]. sch 9 лет назад 0
@sch: У вас определенно есть смысл, спасибо за улучшенный код. Der Hochstapler 9 лет назад 0
1
Daniel Andersson

findкак и предполагалось в ответе Скотта Уилсона, это то, что я бы использовал. Тем не менее, если вам действительно нужно использовать базу данных locate, хакерское решение может быть

sudo strings /var/lib/mlocate/mlocate.db | grep -E '^/.*dirname' 
  • sudo поскольку база данных не может быть непосредственно прочитана обычными пользователями.
  • stringsвырезать метаданные (это также позволяет вам находить каталоги, для которых у вас нет разрешения на чтение, что locateобычно мешает).
  • /var/lib/mlocate/mlocate.dbэто, по-видимому, путь к БД в Ubuntu (в качестве примера. В других дистрибутивах он может быть, например, в других местах /var/lib/slocate/slocate.db).
  • grep -E включить регулярные выражения.
  • ^/.*dirnameбудет совпадать со всеми строками, начинающимися с буквы a /, что происходит со всеми каталогами в БД, после чего следует любой символ несколько раз, за ​​которым следует ваше слово для поиска.

Положительные стороны этого решения:

  • это быстрее чем find,
  • Вы можете использовать все навороты grep(или другие любимые инструменты обработки текста).

Отрицательные стороны:

  • так же, как и locateв целом (БД должна быть обновлена),
  • вам нужен root-доступ.
Да, root-доступ для такой задачи действительно следует избегать. shrx 12 лет назад 0
1
JosephHarriott

Поместив аккуратную линию Оливера Зальцбурга в ваш .bashrc:

# locate directories: # ------------------- locd () { locate $1 | xargs -I {} bash -c 'if [ -d "{}" ]; then echo {}; fi' } 

тогда вы можете вводить locd somethingкаждый раз, когда вы хотите найти только каталоги.

Для меня, чтобы лучше обрабатывать пробелы в каталогах, я использую следующее: `locate -i --all $ 1 | xargs -I {} bash -c 'if [-d "'" {} "'"]; затем эхо "'" {} "'"; fi'` user128063 6 лет назад 0
0
tao

Разместите их как последние строки или там, где они вам больше подходят.
gedit ~ / .bashrc надеюсь, это поможет, ура

#system only
slocate() { locate $@ | egrep -v ˆ/home ; }

#system directories only
dslocate() { for directory in `locate $@ | egrep -v ˆ/home`; do if [ -d "$directory" ]; then echo $directory; fi; done ; }

#whole system directories only
dlocate() { for directory in `locate $@`; do if [ -d "$directory" ]; then echo $directory; fi; done ; }

#local user's only
llocate() { locate $@ | egrep ˆ/home ; }

#local user's directories only
ldlocate() { for directory in `locate $@ | egrep ˆ/home`; do if [ -d "$directory" ]; then echo $directory; fi; done ; }


0
shrx

Я пошел с этим решением:

locate -i "$foldername" | while read line do if [[ -d "$line" && `echo $ | tr [:upper:] [:lower:]` = *`echo $foldername | tr [:upper:] [:lower:]`* ]]; then echo "$line" fi done 
Можете ли вы объяснить, что делает echo $ ? user128063 6 лет назад 0