Я пробовал обе команды, и команда find | grep 'filename'
во много раз медленнее, чем простая find 'filename'
команда.
Каково было бы правильное объяснение этого поведения?
command-line
grep
find
search
file-search
yoyo_fun
источник
источник
time find "$HOME" -name '.profile'
отчеты дольше, чемtime find "$HOME" | grep -F '.profile'
. (17 с против 12 с).grep
вариация будет совпадать в любом местеfind
результата, тогда как совпадение сfind -name
будет совпадать только (в данном случае).find filename
будет быстро . Я вроде предположил, что это опечатка и что имел в виду ОПfind -name filename
. Сfind filename
, толькоfilename
будет рассмотрено (и ничего больше).Ответы:
(Я предполагаю, что GNU
find
здесь)Используя только
будет быстрым, потому что он просто вернет
filename
или имена внутри,filename
если это каталог, или ошибку, если этого имени не существует в текущем каталоге. Это очень быстрая операция, похожая наls filename
(но рекурсивная, еслиfilename
это каталог).По сравнению,
позволит
find
создать список всех имен из текущего каталога и ниже, которыйgrep
затем будет отфильтрован. Это, очевидно, будет гораздо более медленной операцией.Я предполагаю , что то , что было на самом деле предназначены было
Это будет выглядеть
filename
как имя обычного файла в любом месте текущего каталога или ниже.Это будет так же быстро (или сравнительно быстро)
find | grep filename
, ноgrep
решение будет соответствоватьfilename
полному пути каждого найденного имени, аналогично тому, что-path '*filename*'
будет сfind
.Путаница возникает из-за недопонимания того, как
find
работает.Утилита берет несколько путей и возвращает все имена под этими путями.
Затем вы можете ограничить возвращаемые имена, используя различные тесты, которые могут воздействовать на имя файла, путь, метку времени, размер файла, тип файла и т. Д.
Когда ты говоришь
Вы просите
find
перечислить каждое имя, доступное под тремя путямиa
,b
иc
. Если это имена обычных файлов в текущем каталоге, они будут возвращены. Если какое-либо из них окажется именем каталога, оно будет возвращено вместе со всеми последующими именами в этом каталоге.Когда я делаю
Это создает список всех имен в текущем каталоге (
.
) и ниже. Затем он ограничивает имена имен обычных файлов, то есть не каталогов и т-type f
. Д., С. Тогда есть дальнейшее ограничение на имена, которые соответствуютfilename
использованию-name 'filename'
. Строкаfilename
может быть шаблоном подстановки имени файла, например*.txt
(просто не забудьте процитировать его!).Пример:
Кажется, следующее «находит» файл, вызываемый
.profile
в моем домашнем каталоге:Но на самом деле, он просто возвращает все имена по пути
.profile
(есть только одно имя, и это из этого файла).Затем я
cd
поднимаюсь на один уровень и пытаюсь снова:Теперь
find
команда не может найти ни один вызванный путь.profile
.Однако, если я получу его, чтобы посмотреть на текущий каталог, а затем ограничить возвращаемые имена только
.profile
, он также найдет его оттуда:источник
find filename
будет возвращать толькоfilename
еслиfilename
не было типа каталога (или был директории типа, но не было ни сам вход)Нетехническое объяснение: искать Джека в толпе быстрее, чем искать всех в толпе и исключать все из рассмотрения, кроме Джека.
источник
find jack
будет перечислять,jack
если это файл называетсяjack
, или все имена в каталоге, если это каталог. Это неправильное понимание того, какfind
работает.Я еще не понял проблему, но могу дать еще несколько идей.
Как и в случае с Кусаланандой,
find | grep
вызов в моей системе явно быстрее, что не имеет особого смысла. Сначала я предположил некоторую проблему буферизации; эта запись в консоль замедляет время до следующего системного вызова для чтения следующего имени файла. Запись в канал очень быстрая: около 40 МБ / с даже для 32-байтовых записей (на моей довольно медленной системе; 300 МБ / с для блока размером 1 МБ). Таким образом, я предположил, что онfind
может читать из файловой системы быстрее при записи в канал (или файл), так что две операции: чтение путей к файлам и запись в консоль могут выполняться параллельно (чтоfind
как однопотоковый процесс не может выполнять самостоятельно).Это
find
винаСравнивая два звонка
а также
показывает, что
find
делает что-то невероятно глупое (что бы это ни было). Оказывается, он совершенно некомпетентен в исполнении-name '*.txt'
.Может зависеть от отношения ввода / вывода
Вы можете подумать, что
find -name
побеждает, если писать очень мало. Но это просто становится более смущающим дляfind
. Он проигрывает, даже если нечего писать против файлов 200К (13М данных канала) дляgrep
:find
может быть так быстро, какgrep
, хотяОказывается, что
find
глупость сname
не распространяется на другие тесты. Вместо этого используйте регулярное выражение, и проблема исчезла:Я думаю, это можно считать ошибкой. Кто-нибудь готов подать отчет об ошибке? Моя версия найти (GNU findutils) 4.6.0
источник
-name
тест, то, возможно, он был медленнее из-за того, что содержимое каталога не кэшировалось. (При тестировании-name
и-regex
я считаю , они берут примерно в то же время, по крайней мере , один раз эффект кэша было принято во внимание Конечно , это может быть просто другая версия.find
...)find
версия найти (GNU findutils) 4.6.0-name '*.txt'
замедляетсяfind
? Он должен сделать дополнительную работу, проверяя каждое имя файла.find
должен писать меньше данных. И запись в канал - намного более медленная операция./dev/null
как-то использовать меньше системного времени.Обратите внимание : я предполагаю, что вы имеете в виду
find . -name filename
(в противном случае вы ищете разные вещи; наfind filename
самом деле изучаете путь, называемый filename , который может почти не содержать файлов, поэтому очень быстро завершается).Предположим, у вас есть каталог с пятью тысячами файлов. В большинстве файловых систем эти файлы на самом деле хранятся в древовидной структуре , которая позволяет быстро найти любой файл.
Так что, когда вы просите ,
find
чтобы найти файл, имя которого требуется только проверка,find
будет просить для этого файла, и этот файл только для базовой файловой системы, которая будет читать очень мало страниц из хранилища массы. Поэтому, если файловая система того стоит, эта операция будет выполняться намного быстрее, чем обход всего дерева для получения всех записей.Когда вы спрашиваете о простой,
find
но это именно то, что вы делаете, вы пересекаете все дерево, читая. Каждый. Один. Вступление. С большими каталогами это может быть проблемой (именно по этой причине несколько программ, которым нужно хранить много файлов на диске, будут создавать «деревья каталогов» глубиной в два или три компонента: таким образом, каждый отдельный лист должен содержать меньше файлы).источник
Предположим, что файл / john / paul / george / ringo / beatles существует, и файл, который вы ищете, называется 'stone'
find сравнивает «битлы» с «камнями» и отбрасывает их, когда «s» и «b» не совпадают.
В этом случае find передает '/ john / paul / george / ringo / beatles' в grep, и grep должен будет пройти весь путь, прежде чем определить, соответствует ли он.
поэтому grep делает гораздо больше работы, поэтому это занимает больше времени
источник