Я написал инструмент в Crystal, который принимает некоторые параметры командной строки и превращает их, по сути, в «find stuff | xargs grep», где xargs указывает использовать несколько процессов. Это запускается через Process.run, а вывод и ошибка перенаправляются в пользовательский объект ввода-вывода, который немного фильтрует то, что выходит из grep, записывая все, что не фильтруется, в STDOUT.
Когда я запускаю это в обычном режиме, в основном кажется, что все работает нормально. Однако, похоже, есть некоторые случаи, когда вывод прерывается до завершения поиска, поэтому я не уверен, что могу полностью доверять результатам. Однако, когда я перенаправляю вывод этой команды в grep, он всегда прерывает поиск и говорит «grep: write error». Я понятия не имею, почему это происходит, и хотел бы получить помощь. В конце концов я, скорее всего, перепишу это, чтобы делать все на чистом Crystal, но пока это быстрое решение для поиска в кодовой базе, над которой я работаю.
Вот код, который запускается:
class FindFilterIO
include IO
@@generic_filter = [".diff", ".iml", "/target/"]
@@web_filter = [".css", ".js", ".jsp", ".ftl"]
def initialize(@web_search : Bool = false)
end
def read(slice : Bytes)
raise "FindFilterIO does not support reading!"
end
def write(slice : Bytes)
str = String.new slice
if @@generic_filter.any? { |e| str.includes? e }
return
end
if @web_search
if !@@web_filter.any? { |e| str.includes? e }
return
end
end
STDOUT.write(slice)
end
end
cmd = "find . -not \\( -path ./.svn -prune \\) " \
"-not \\( -path ./.idea -prune \\) " \
"-type f -print0 " \
"| xargs -0 -P 1 -n 100 grep -E -n --color=always "
cmd += if @html_id
"'id=['\"'\"'\"]#{@search_text}['\"'\"'\"]|\##{@search_text}'"
elsif @html_class
"'class=['\"'\"'\"]#{@search_text}['\"'\"'\"]|\\.#{@search_text}'"
else
"'#{@search_text}'"
end
io = FindFilterIO.new web_search: (@html_id || @html_class)
Process.run(cmd, output: io, error: io, shell: true, chdir: File.join(@env.home_dir, @env.branch, "repodir"))