This script can find strings in a file and also find files whose names include a certain string.

This script can be run as a shell script, and also as an API.

To install it run pastebin get qRmi8Zf6 in a shell.

Here is the source:


-- Set local variables
-- This is an internal function called by updateIndex to initalize the search index.
function updateIndexFile(path)
	indexedFiles[path] = ""
	local file = fs.open(path, "r")
	if file then
		local line = file.readAll()
		file.close()
		indexedFiles[path] = line
	else
		indexedFiles[path] = ""
	end
end

-- This is an internal function called by rebuildIndex to initalize the search index.
-- It loops through the directory list and calls itself if it finds a directory.
function updateIndex(path)
	if fs.isDir(path) then
		for k, v in pairs(fs.list(path)) do
			if fs.isDir(path.."/"..v) then
				updateIndex(path.."/"..v)
			else
				updateIndexFile(path.."/"..v)
			end
		end
	elseif fs.exists(path) then
		updateIndexFile(path)
	end
end

-- This is an internal function run by Lua Script System to initalize the search index.
-- It is run on startup to initalize the index. If you are not using LuaSS then you need to run this before the
-- first time you search files using the searchFiles or searchFileName functions given by this API.
-- Currently it just calls updateIndex to index the root directory.
function rebuildIndex()
	updateIndex("")
end

-- This is an internal function used to check if a file should be included in the table returned by searchFiles.
function findStringInIndexSearchFiles(path, sSearch)
	local contents = indexedFiles[path]
	local startHere = 0
	while true do
		local nextSlash = string.find(string.sub(contents, startHere, -1), sSearch)
		if not nextSlash then
			return
		else
			fileContentIndex[sSearch][#fileContentIndex[sSearch] + 1] = path
			return true
		end
		nextSlash = nextSlash + startHere
		tab = tab + 1
		startHere = nextSlash
	end
end

-- This is an internal function used to check if a file should be included in the table returned by searchFileNames.
function findStringInIndexSearchFileNames(path, sSearch)
	local match = string.find(path, sSearch)
	if match then
		fileNameIndex[sSearch][#fileNameIndex[sSearch] + 1] = path
		return true
	end
end

function checkIfIndexed()
	if not indexedFiles then
		indexedFiles = {} -- This table is used to store indexed file contents.
		fileContentIndex = {} -- This table is used to store file content matches.
		fileNameIndex = {} -- This table is used to store file name matches.
		print("Indexing Files...")
		rebuildIndex()
	end
end

-- This function searches inside files for the searchstring sSearch.
function searchFiles(sSearch)
	checkIfIndexed()
	local tab = fileContentIndex[sSearch]
	if tab then
		return tab
	else
		fileContentIndex[sSearch] = {}
		for k, v in pairs(indexedFiles) do
			findStringInIndexSearchFiles(k, sSearch)
		end
		return fileContentIndex[sSearch]
	end
end

-- This function searches for files with names that include the string sSearch.
function searchFileNames(sSearch)
	checkIfIndexed()
	local tab = fileNameIndex[sSearch]
	if tab then
		return tab
	else
		fileNameIndex[sSearch] = {}
		for k, v in pairs(indexedFiles) do
			findStringInIndexSearchFileNames(k, sSearch)
		end
		return fileNameIndex[sSearch]
	end
end

local function printUsage()
	if shell then
		print("To search files, use "..shell.getRunningProgram().." search <name>.")
		print("To search file names, use "..shell.getRunningProgram().." find <name>.")
		print("To rebuild the index, use "..shell.getRunningProgram().." rebuild.")
	end
end

local tArgs = {...}
if #tArgs > 0 then
	if #tArgs > 1 then
		if tArgs[1] == "find" then
			textutils.pagedTabulate(searchFileNames(tArgs[2]))
		elseif tArgs[1] == "search" then
			textutils.pagedTabulate(searchFiles(tArgs[2]))
		else
			printUsage()
		end
	elseif tArgs[1] == "rebuild" then
		rebuildIndex()
	else
		printUsage()
	end
else
	if shell then
		checkIfIndexed()
		printUsage()
	end
end
</name></name>