How to search within notebooks on Windows 10?

Here is a potential workaround.

Windows 10 has a feature called the Windows Subsystem for Linux. You should be able to activate from the start menu and typing "Windows Features" and selecting the first hit. Then, turn it on as shown in the image.

Windows Subsystem For Linux

Linux has a command called grep that provides many options to search text files. After installing, you can type bash into the start window and use the bash command shell to search files using grep. For example, the command grep -RH NotebookDirectory --include="*.nb" * will perform a recursive directory search for the term NotebookDirectory for all files matching the pattern *.nb.

Updated More Robust Answer

I have a Windows 7 and 10 system that both have the Linux emulator Cygwin installed. Since the Windows 10 machine has both Cygwin and the Subsystem for Linux, it can be confusing about which Linux system was called. It turns out that grep is stored in /bin/grep and /usr/bin/grep for the Subsystem for Linux and Cygwin, respectively.

I used the linux command which grep and RunProcess to confirm that my initial answer was picking up the Cygwin grep.

RunProcess[{"which", "grep"}, "StandardOutput"]
(* "/usr/bin/grep" *)

To access the Subsystem for Linux require that we prepend bash -c to the command or

RunProcess[{"bash", "-c", "which grep"}, "StandardOutput"]
(* "/bin/grep" *)

A more robust code that can handle either Cygwin or the Subsystem for Linux follows

SetDirectory[NotebookDirectory[]];
grepRecurse[searchterm_, filepattern_] := {"bash", "-c", 
  StringTemplate["grep -RH \"`1`\" --include=\"`2`\" *"][searchterm, 
   filepattern]}
cmd = grepRecurse["NotebookDirectory", "Int*.nb"];
s = RunProcess[cmd, "StandardOutput"];
Column@StringSplit[StringSplit[s, RegularExpression["\r?\n"]], ":"][[
  All, 1]]

Code with bash -c

Original Answer That Might Only Work with Cygwin in Path

Alternatively, you can issue the command from Mathematica directly using RunProcess workflow as shown below.

SetDirectory[NotebookDirectory[]];
grepRecurse[searchterm_, filepattern_] := {"grep", "-RH", 
   StringTemplate["\"`1`\""][searchterm], 
   StringTemplate["--include=\"`1`\""][filepattern], "*"};
cmd = grepRecurse["NotebookDirectory", "Int*.nb"];
s = RunProcess[cmd, "StandardOutput"];
Column@StringSplit[StringSplit[s, RegularExpression["\r?\n"]], 
   ":"][[All, 1]]

RunProcess Example


Some time ago I've written a search routine which allows searching inside of Notebooks using string patterns:

  • Searching a phrase in all *.nb files

Other solutions from that thread can also be of interest for you.


Alternatively you can program your own search routine on the base of one of the following functions:

  • Import[nbFilePath, "Plaintext"]

  • NotebookImport[nb, _ ->"InputText"]

  • First[FrontEndExecute[FrontEnd`ExportPacket[nb, "PlainText"]]]

You can find additional information on their usage in the following threads:

  • Programmatically convert notebook input cells to text file

  • How to convert arbitrary raw boxes directly into String?

Note however that Import[nbFilePath, "Plaintext"] is based on "NBImport.exe" which has long-standing bug in importing files with non-ASCII filepaths.