FGREP 1.83 ---------- Purpose ------- FGREP (Fast GREP) is a small utility that can be used to find strings of characters in ASCII text files, and arbitrary sequences of bytes in other files. String search capabilities are not extensive (no regular expressions), but FGREP is small and very, very fast. FGREP is intended to replace the FIND filter with something faster and more flexible. UNIX people: we fully realize that this isn't the grep or fgrep with which you are familiar. We know that the RE in GREP means "regular expressions" and that we don't support regular expressions. However, the name serves to point people in the right direction. Please don't write to tell us that this "isn't really fgrep". FGREP386 -------- FGREP386.COM is a version of FGREP.COM that requires an 80386 or better. It should be slightly faster than FGREP.COM (don't expect anything spectacular). If you have an 80386 a higher CPU, just erase FGREP.COM and rename FGREP386.COM to FGREP.COM. New in version 1.83 ------------------- This is a bugfix release only. Syntax ------ FGREP's syntax is FGREP [options] target {@file} There are many "options", but the most common use is very simple: FGREP hello myfile.txt This command would display all lines of MYFILE.TXT that contain the character string "hello". Targets ------- The target is what you're looking for in the file. There are two ways to specify targets: as strings and as series of hexadecimal bytes. The two can be combined in a single target specification. Strings are sequences of ASCII characters, like "hello". Normally, you can just type in the string and forget it, but you may have to "delimit" the string, i.e., bracket it by a pair of matching non-alphanumeric characters (anything except '-' and '$'): 'string' /string/ .string. Choose a delimiter that does not appear in the string. This is no good: 'you've made a mistake' Delimiters are required for a string target if any of these four conditions are met: -- it is combined with hex byte sequences (more below) -- it contains spaces or tabs -- it begins with a non-alphanumeric character -- it contains the redirection characters < > |. In the last case, the string MUST be delimited by double quotes ("), otherwise DOS will interpret it as redirection. Examples of valid string targets: mov ax "two words" (requires delimiter: contains a space) '/7' (begins with non-alphanumeric) "f->x" (contains ">", must use double quotes) It is always OK to delimit a string, even if delimiters are unnecessary. REMEMBER that if the target contains DOS redirection characters (<, >, or |), it MUST be delimited with double quotes ("") or DOS will try to perform unwanted redirection. For example: FGREP "a <= b" myfile.pas Hex byte sequences are used for binary file searching when the bytes to be searched for are non-displayable characters or make no sense as strings (e.g., program code). They are specified as pairs of hexadecimal bytes introduced by a leading '$': $EF $CD21 (CDh, 21h) $CD$21 (identical; either format is OK) $00FFFE00 (00h, FFh, FEh, 00h) $CD 21 (ILLEGAL: no spaces permitted) You can combine strings and hex sequences by using a '+': "abc"+$E74A+"def" Target wildcards ---------------- String targets (not hex targets) may contain one or more "?" wildcards. The ? will match any single non-null character in the file. E.g., "[?i]" will match "[si]", "[di]", etc., but not "[i]". Wildcards are not permitted when hex byte sequences are used. If you want to search for the '?' character literally, use '\?'. For example, the target what\? will search for the literal string "what?". Specifying target files ----------------------- You can list zero (see "Redirection"), one, or multiple files to be searched. Files listed may include DOS's * and ? wildcards. Paths may be specified. Examples: myfile.txt *.txt *.* this.c that.c other.c *.c *.pas C:\UTIL\*.* D:\SYS\*.* E:\LIBRARY\*.D?C You may also specify just a drive or directory name. If you specify just a drive, FGREP searches all files in the current directory of the specified drive. If you specify a directory name, FGREP searches all files in the specified directory. Examples: c: [same as c:*.*] c: d: [same as c:*.* d:*.*] \src [same as \src\*.*] d:\src [same as d:\src\*.*] You can also search all subdirectories of the directories you specify; see the discussion of the -r option in the "Options" section below. File lists ---------- If the name of a file on the command line is prefixed with an '@' character (e.g., '@list.txt'), the file is assumed to be a text file containing the names of files to be searched. For example: fgrep hello @files.lst FGREP will assume that the file FILES.LST is a text file that contains the names of files to be searched. Each line of such a file should contain the name(s) of one or more files to be searched. Files in file lists are specified exactly as are files named on the command line, except that you can't use another '@' file list; that is, file lists can't be nested. Here is an example of a valid list file: this.c c:\c\*.c d:\c\*.c d:\misc\*.txt The name specified for the list file cannot contain wildcards; that is, this is illegal: fgrep hello @lists.* (WRONG) If you want to search for text in a file whose name begins with an '@', use a double '@'. For example, fgrep hello @@foo.txt will search for 'hello' in the file @FOO.TXT. Redirection ----------- If no file is listed, FGREP will take its input from the standard input device, allowing it to be used as a filter. For example, the command: DIR | fgrep pas would display any lines from a directory listing that contain the string "pas". Or, DIR | fgrep "" would list all subdirectories of the current directory. This command: pkunzip -c myzip foo.txt | FGREP somestring would display all lines from the file FOO.TXT in the ZIP file MYZIP that contain "somestring" (the -c option causes PKUNZIP to extract FOO.TXT to the console device instead of to a disk file). FGREP will terminate with an error if no file is listed and standard input is not redirected. Otherwise, it would be silently waiting for keyboard input, possibly leading you to believe that it had died. Examples of use --------------- Here are some examples of FGREP use: 1. List all lines of MYFILE.TXT containing "hello" FGREP hello myfile.txt 2. List all lines of all *.C files in the current directory that contain "include foo.c": FGREP "include foo.c" *.c 3. List all lines from FILEA.EXT, FILEB.EXT, and FILEC.EXT that contain the string "abcd" followed by any character: FGREP abcd? filea.ext fileb.ext filec.ext 4. Display occurrences of the byte CDh followed by 21h (a DOS call) in the program MYPROG.EXE: FGREP $CD21 myprog.exe 5. Display occurrences of the string "abc" followed by a byte of zeroes in all files in the C:\UTIL and D:\SYS directories: FGREP 'abc' + $00 c:\util\*.* d:\sys\*.* Output ------ FGREP's default screen output looks like this: **File [text of lines containing string] **File [text of lines containing string] You can add line numbers to the display by using the -l option (see below). If the "Microsoft format" option (-m or -M, see below) is used, the output is in this format: filename(linenum): text This format is the standard format used by Microsoft (R) language products and by its MEGREP. If -m is used, only the filename and extension are displayed; if -M is used, the complete filespec, including path, is displayed. When a hex byte sequence or the -b switch is specified, FGREP uses the binary output mode. See below for details. All useful output is sent to the standard output device, so it may be piped to other programs or redirected to file: FGREP target filea | yourprog FGREP target filea > test.txt Error messages and the program logo will appear always appear on the console device, and will never appear in redirected or piped output (unless you use the -Zl option). FGREP returns an errorlevel to the operating system. It will be one of: 0: String not found in any file 1: String found in at least one file 255: Error (file read error or bad parameter) Options ------- These are the option switches that control how FGREP works. All switches are case-insensitive except -m/M, -b/B, and -r/-R; for example, either -a or -A will set ANSI mode. All switches must precede the target on the command line, but they may be in any order. If you specify conflicting switches, the last one will be effective. Options may be specified on the command line or in an environment variable (see below). -a is ANSI mode. If you have ANSI.SYS (or equivalent) installed, escape characters (ASCII 27) in displayed text lines can cause odd results. If you use the -A switch, FGREP will substitute an upside-down question mark (¨) for ESC, possibly resulting in cleaner displays. You'll only need this switch if you have ANSI installed and there are ESC characters in the files you're scanning. Ignored in binary mode. -b specifies binary search mode/output. This switch is automatically set if you use a hex byte sequence in the target. See "binary search" below. -B specifies a case insensitive binary search. -c makes the search case sensitive ("String" will not match "string" or "STRING"). Normally, FGREP ignores case. This switch is ignored in binary mode. Using -c will generally result in faster searches. -e specifies that ONLY an errorlevel is to be returned. There will be no display at all. This is equivalent to the combination -s0. -f causes the "**File" header lines to be displayed only for those files that contain the search string. -g gets a user-supplied character frequency table. See "Using your own frequency table" below. -i specifies an "input field" or "search field," allowing you to search only a part of each line. See "Limiting searches to specified columns", below. -j left justifies output, i.e., removes any leading spaces from output text. Ignored in binary mode. -l adds line numbers to FGREP's output. Ignored in binary mode. -m or -M specify Microsoft (R) output format. See "Output" above. If -m is used, only the filename will appear. If -M is used, the full filespec (including drive and path) will be included. Unless the files being searched are on CD-ROM drives, the path is "fully qualified", i.e., it begins from the root directory and resolves any "." and ".." references in your target file specification. If the files are on CD-ROM drives, the path may not be fully qualified. -o specifies a maximum output width. It should be followed by a decimal number from 0 to 50000. For example, -o40 causes FGREP to truncate all output to a maximum of 40 characters per line. If you specify -o0, no text will be displayed at all. This is not useful for the normal display, but you can use this feature with -l, -m, or -M if you want to display just the line numbers where the text was found but not the text itself. Do not confuse the "o" (Output) option with the "0" (zero text) option. -o is ignored in binary mode. -p pauses on full screen of output. -r recursive (subdirectory) search. For each filespec provided, FGREP searches the specified directory and all subdirectories for matching file names. If no directory is specified, FGREP begins the search with the current directory. For example: fgrep -r "text" *.c d:\src\*.c This command searches all *.c files in the current directory and all of its subdirectories; then it searches all *.c files in D:\SRC and all of its subdirectories. -R another recursive search; differs from -r in that the top level directory is NOT searched. For example, if the filename is specified on the command line as \WP\*.*, fgrep will search the subdirectories of \WP but not \WP itself. This can be useful, for example, if you have a text editor directory with document subdirectories and you want to search only the documents (not the text editor files themselves). -s suppresses the "**File" header lines in the output. -t displays only the actual text found (rather than the entire line containing the text). This is useful with wildcards; for example, the command fgrep -t "??rse" dict.txt might display "parse", "purse", "horse", etc. (perhaps displaying all words from a text dictionary that match the pattern). Note that the displayed text will be all lowercase if the search is case insensitive; and, any embedded spaces will be missing if the search is white space insensitive (-w option). -t and -v (reVerse search) are incompatible. You can combine -t with an input field and wildcards to display "fields" of a file. For example: fgrep -t -i70,75 "??????" test.dat This command would display columns 70-75 of all lines in the file. -v provides a reVerse or negative search. That is, all lines that do NOT contain the specified string are displayed. This provides a handy way to get rid of lines containing specified text. Suppose, for example, that you have a file containing a list of file names, and you are interested in all files EXCEPT those that contain a '$' in the name (perhaps they are temporary files): FGREP -v "$" filename This switch is ignored in binary mode. -w indicates that white space (blanks and tabs) is not significant. White space in both the search string and the input file will be ignored. If -w is specified, the wildcard character (?) will match any nonblank character. Ignored in binary mode. -x suppresses the display of the program logo/copyright. -Za causes FGREP to echo its command line arguments to the standard output device. This allows the parameters to be captured in redirected output files and is intended mostly for use by other programs that perform post-processing on FGREP output. -Zb filter "bells" from output. Before displaying the text of lines containing the target string, FGREP changes any "bell" characters (character 7) to spaces, which prevents the system from beeping at you. -Zd causes FGREP to display the name of each directory as it begins to search the directory. This is intended mostly for recursive searches (-r option). -Zl causes FGREP to send its logo to the standard output device instead of the standard error device. This allows the logo and version number to be captured in redirected output files and is intended mostly for use by other programs that perform post-processing on FGREP output. -Zv tells FGREP to ignore the FGREP= environment variable (see below). If present, this must be the first option specified. -0 ("0" text lines) suppresses the display of lines of text containing the specified string. FGREP will skip immediately to the next file when the string is found. The -0 option is most commonly used with -f (-f0) to simply display a list of files containing the target string. Note that -0 is different in effect from -o0; when combined with -l or -m, the -o0 option will display line numbers and/or filenames, but -0 will display nothing. -1 ("1" text line) specifies that only the first line containing containing the specified string in each file will be displayed. FGREP will then skip immediately to the next file. -@ causes FGREP to display ONLY a list of files that contain the search target. No text is displayed or other information is displayed. This option is useful to create a file containing a list of files for further processing by other programs. For example: FGREP -@ "stuff" *.txt > list.txt On completion of this run, the file LIST.TXT will contain a list of the files that contain "stuff". -? causes FGREP to send its usage/help information to the standard output device so that it can be piped or redirected. The usage info is normally sent to the standard error device, which can't be redirected. Using -? allows you to pipe the usage information through MORE or some other utility so that you can review it (it's now longer than most screens will be able to display). FGREP environment variable -------------------------- You can place frequently-used options in an environment variable named FGREP. For example, if you always want output displayed in "Microsoft" format: SET FGREP=-m This is equivalent to using the -m option in every FGREP command. The -Zv option causes FGREP to ignore the contents of the FGREP environment variable. Use this when you don't want the options set in the variable to affect a particular FGREP run. For example, the command FGREP -Zv foo *.txt would result in a standard format display even if FGREP= is set as in the above example (SET FGREP=-m). If present, the -Zv options must be first on the command line, preceding all other options, the target. and the filespecs. Binary search ------------- If you use a hexadecimal byte sequence in your target, or if you specify the -b or -B switch, FGREP uses a "binary" mode rather than the usual text mode. In this mode, FGREP is not concerned with "lines" of text and can be used to search any file for arbitrary sequences of bytes. The output format is different. Because there are no "lines" to display, FGREP shows the locations in the file where the target was found and the sixteen bytes surrounding the find (eight before, and eight after). Here is the output format, split into two lines: nnnnnnnn: n n n n n n n n . n n n n n n n n cccccccc . cccccccc The initial sequence is the 32-bit file offset where the target was found, in hex. For example, 0001C47A: indicates that the target was found at file offset 1C47A. The next two series (n n n ...) represent the eight bytes before and after the target (which, logically, occurred at the '.' position): 4B 7F 37 42 42 44 FF FF . 20 20 21 48 48 4F 3C 22 The final series (ccc...) represents the same sixteen bytes displayed as characters. Nondisplayable characters are shown as periods. Unlike text searches, binary searches are normally case sensitive. That is, $41 ('A') will not match $61 ('a'). If you want a binary search to be case INsensitive ($41 matches both $41 and $61), use -B instead of -b. The normal case sensitive switch (-c) is ignored. These switches are also ignored in binary mode: -a ANSI mode -l Show line numbers -m/M "Microsoft" format -t Display found text only -v Inverse search -w Whitespace insensitive -Zb Filter "bell" characters Also, wildcards are not permitted in string targets when a binary search is used. Limiting searches to specified columns -------------------------------------- The -i option specifies an input search field. You can use this if you are only interested in text that appears in certain columns of your files. The syntax of the option is: -i#[,#] where the first # is the starting column and the second is the ending column. The second # is optional; if it is not present, FGREP will only find your target if it begins in the specified starting column. The first column of each line is column 1. Examples: fgrep -i20,30 stuff *.txt Looks for the word "stuff" in text columns 20 through 30. fgrep -i1 stuff *.txt Looks for lines that begin with the word "stuff". fgrep -i10 stuff *.txt Looks for lines with the word "stuff" beginning at column 10. In order for text to be "found," it must appear entirely within the search field. Using the first example, the only matches would be lines that contain "stuff" beginning in columns 20 through 26: 1 2 2 2 2 2 2 2 2 2 2 3 3 9 0 1 2 3 4 5 6 7 8 9 0 1 s t u f f (No match; 's' in col 19) s t u f f (Match) s t u f f (Match) s t u f f (No match; 'f' in col 31) Note that using the -i option forces FGREP to use the "slower" of its two search techniques (see below). It will probably speed up searches that use the -L, -m/m, -V, or -W options (all of which also require the slower search), but it may slow down other searches. "Fast" search technique ----------------------- FGREP uses two different search techniques. Both are fast, but one is faster than the other. The faster search will be used UNLESS any of these conditions are met: - line numbers or "Microsoft" format used (-L or -m/M) - the search is reVerse (-v) - the search is whitespace insensitive (-w) - the target string contains wildcards ("?") - the search is limited to specified columns (-i) For other searches, the "fast" technique is typically 20-40% faster than the "slow", although we've seen 70% improvements in some cases. The technique has its roots in searching for unusual (less frequently used) characters, so it will make more of a difference searching for "squeeze" (q is a little-used letter) than it will searching for "eat". Using your own frequency tables: BUILDFT ---------------------------------------- In most cases, FGREP uses a built-in character frequency table to help find strings as fast as possible. Because FGREP was originally intended for use by programmers, this frequency table was created by analyzing a great deal of program source code written in the C, Pascal, and assembler programming languages. While the table is pretty good for programmers using the above languages, it may not be ideal for your use, because the character frequencies in your files may be very different from the frequencies in program source code files. You can use the BUILDFT program, which is included with FGREP, to create your own frequency tables for FGREP to use, possibly resulting in faster searches. Speed differences between using the default table and custom tables depend on several factors; in specific searches, you may see a big difference, a small difference, or no detectable difference. In some cases, it's even possible that using the default table could be faster than using a custom table. In other words, your mileage may vary. FGREP does NOT use a character frequency table if your search target contains wildcards (? characters). Creating frequency tables ------------------------- To create frequency tables, just run BUILDFT and specify one or more filenames (which may include paths and wildcards): BUILDFT file {file} The file name(s) specify which files you want BUILDFT to scan. It reads these files, counts characters, and stores the resulting frequency table in a disk file named FGREP.FT. For example: BUILDFT *.txt d:\bd\*.bas This command reads all *.TXT files in the current directory and *.BAS in D:\BD, counts characters, and creates a new FGREP frequency table in the file FGREP.FT (see below for information on how to use the new frequency table). Options ------- There are several options you can use when creating frequency tables. Options are not case-sensitive and may be specified in any order. Multiple options must be separated by at least one space. The options are as follows: The -R option causes BUILDFT to search subdirectories recursively, just like FGREP's -R option. For example, this command counts the characters in all *.TXT files on drives C, D, and E: BUILDFT -r c:\*.txt d:\*.txt e:\*.txt The -M option causes BUILDFT to merge previous character counts with new character counts. Use this to merge the results of multiple BUILDFT runs. The following series of commands is identical in effect to the previous example: BUILDFT -r c:\*.txt BUILDFT -r -m d:\*.txt BUILDFT -r -m e:\*.txt The first command (which does not have the -M option) creates a new frequency table from the character counts of TXT files on drive C. The second command counts the characters in TXT files on drive D; because it uses -M, the new character counts are added to the previous counts from drive C. The third command does the same thing for drive E. The -F option allows you to specify a filename other than FGREP.FT for the frequency table file. For example, this command creates a file called C.FFT instead of FGREP.FT: BUILDFT -fC.FFT -r *.c Finally, the -D option causes BUILDFT to display the frequency table after it has been created: BUILDFT -d *.c This command builds the frequency table file and displays the results. The display might look like this: Cod Chr Freq Count --- --- ---- ----- 32 65534 161601 101 e 6179 24716 42 t 4350 17400 ... The first column is the ASCII code for the character (e.g., the ASCII code for the letter 'e' is 101). The second column is the character itself. The third column is FGREP's frequency factor, which is the actual number that FGREP uses. For all characters other than (character 32), the value will be between 0 and 32767, with higher numbers representing higher frequencies (for technical reasons, the space character always has a frequency value of 65534). The final column shows the actual number of occurrences of each character in the file(s) scanned. If you specify -D without any filenames to scan, BUILDFT simply displays the contents of an existing frequency table file without changing it. Examples: BUILDFT -d BUILDFD -d -fTEXT.FT The first command displays the character frequencies from the default file, FGREP.FT. The second command displays the frequencies from the file TEXT.FT. Using frequency tables ---------------------- To use a frequency table created by BUILDFT, just run FGREP with the -g option, which tells it to "Get" the frequency table from FGREP.FT. For example: fgrep -g "stuff" *.txt If the frequency table is in a file other than FGREP.FT, or if FGREP.FT isn't in the current directory, specify the filename and/or path: fgrep -gTEXT.FT "stuff" *.txt fgrep -gC:\UTIL\FGREP.FT "stuff" *.txt Note that this method of using custom frequency tables is not efficient for searching small files; the extra time required to load the frequency table will "drown out" any improvements in search speed. Replacing the built-in frequency table -------------------------------------- Alternatively, you can use BUILDFT to permanently replace FGREP's built-in table. This option copies a frequency table from a file previously created by BUILDFT into the FGREP program file; after you've done this, you don't need to use the -g option when you run FGREP. To do this, just run BUILDFT with the -U option: BUILDFT -u This copies the frequency table from the file FGREP.FT (the default name) into the FGREP program file, FGREP.COM, replacing the built-in frequency table. Of course, when you use the -U option (which alters the FGREP.COM program file), you will want to save a copy of the original program file somewhere! To specify a frequency table file other than FGREP.FT, use the -F option (just as you did when you created the table file): BUILDFT -fTEXT.FT -u You can also use the -P (Program file) option to specify that the name of the FGREP program file is something other than FGREP.COM. For example: BUILDFT -pFGREPC.COM -fTEXT.FT -u This command copies the frequency table from TEXT.FT into a copy of FGREP named FGREPC.COM. You can use this feature to build custom versions of FGREP for different types of files. For example: copy fgrep.com fgrepc.com buildft *.c *.h buildft -u -pFGREPC.COM You now have a custom version of FGREP.COM (FGREPC.COM) that has a special frequency table just for C program source files (which usually have the extensions .C or .H). When you use -U, the only other options you can use are -P and -F; no others are permitted. Notes on FGREP -------------- 1. The -f and -s switches are mutually exclusive. If both are specified, the last one will be effective. 2. The -M/m and -s switches are mutually exclusive. If both are specified, the last one will be effective. 3. The -v and -t switches are mutually exclusive. If both are specified, FGREP terminates with an error. 4. The -i and -w switches are mutually exclusive. If both are specified, FGREP terminates with an error. 5. If you specify the -e switch, FGREP will stop processing as soon as a nonzero errorlevel is determined. The -e switch is really designed to enable other programs to determine whether or not a specific file contains a specific string in as little time as possible. For example, here's an algorithm that will quickly 'touch' all files that do NOT contain a specified string: for file in (*.*) do FGREP -e string file if errorlevel < 1 then touch file end 6. The -s switch is automatically set when input is taken from redirected standard input. 7. FGREP optimizes the combination -s0 (suppress headers, no text) to -e. 8. If you just want to know which files contain a string, use -0; it saves time because the rest of the file (after the first hit) is skipped. The combination -f0 is particularly efficient for this as it will simply display a list of files that contain the string. 9. There is a maximum line length of 500 characters if any of the -V, -W, -L, or -M switches are used; otherwise, the maximum line length is about 60K (may be less under low memory conditions). 10. FGREP expects standard text files; binary files will yield weird results unless you use the -b/B binary switch. For the most part, word processor documents are NOT text files; they are special files in proprietary formats that contain a good deal of non-text information. Lines can be terminated by any of CR, LF, or CR+LF. 11. If output is redirected to disk, make sure there is enough space available. The program does not check. A little note from the author ----------------------------- I get lots of calls and emails like this: I love FGREP because it's so fast. It outperforms the next fastest text search utility I have by two-to-one. If you could just add (regular expressions | boolean searches), it would be ideal. Now, there are lots of text search programs with boolean searches and regular expressions out there (including the real GREPs). I use some of them myself. But one day it occurred to me that 95% or more of my searches were very simple (not requiring either feature) and that I was probably incurring a speed penalty for flexibility that I wasn't using much. So I decided to write a program that would handle only these simpler searches, but much faster. The main reason why FGREP is so fast is that I've been able to highly optimize these simple searches. If I added regular expressions or boolean searches, this optimization would not be possible, and the main reason for the existence of the program (speed) would go away. So. I'm always glad to get comments and suggestions on FGREP, so please keep calling and writing. But I won't be adding regular expressions or boolean searches. If you need those, there are plenty of fancier search programs available (including the real grep). The penalty for greater flexibility is usually increased search time. However, since so many people have asked about boolean searches, read on... How to use FGREP for AND/OR searches ------------------------------------ It is quite easy to use FGREP to perform an "and" search by simply running it twice, piping the output from the first run into the second run. For example, suppose you want to see lines containing both "trace" and "reset" in any file with a "C" extension: fgrep -m "trace" *.c | fgrep "reset" The first run finds lines containing the word "trace" in the C files; the output of this run is them piped into a second run, which searches for "reset". The output of this run then will contain only lines with both "trace" and "reset". The -m option in the first run is useful when you're searching multiple files (as we are here) because it specifies the filename with each output line; without this option it would be hard to know which files the found lines came from. Note that "*.C" is not re-specified for the second run. You want the input to come from the first run, not from the original files. Even though FGREP runs twice, it's our experience that it's still to do this than to use most of the traditional search programs that directly support an AND search. OR searches (e.g., lines with "trace" OR "reset) are a bit more difficult. Of course, if you don't care about duplicate finds, you can simply run FGREP twice (once for each word): fgrep "trace" *.c > foo fgrep "reset" *.c >> foo type foo If you don't want to see duplicate lines, you'll need some additional tools. You'll need a sort program (SORT comes with DOS, so that's easy) and a tool to eliminate duplicate lines. There are several of these available in public domain and freeware (e.g., "UNIQ"). Here's the basic technique: fgrep -m "trace" *.c > temp fgrep -m "reset" *.c >> temp sort < temp | uniq The two runs of fgrep create a file named TEMP with all lines that contain either "trace" or "reset". The third command sorts this file and pipes the sorted lines into UNIQ, which eliminates duplicate lines and displays the results. Version 1.83 ------------ Corrects a problem with spurious lines being displayed in certain reverse searches (-v option). Version 1.82 ------------ Adds -j and -? options. Corrects a problem using BUILDFT to update the FGREP program file with a new frequency table (problem in v.1.81 only). Sends usage information to stdout instead of stderr. Version 1.81 ------------ Adds FGREP environment variable and -Zv option. Adds -R option. Less crashy when used on binary files without -b option. Corrected problem searching files on CD-ROM drives. Corrected problems with -t mode. Version 1.80 ------------ Adds recursive search (-r option). Adds ability to specify just drive/directory (assumes *.*). Adds -i option to specify search fields. Adds -@, -t, -Za, -Zb, -Zd, and -Zl options. Always includes full path when displaying filenames. Adds user-specified frequency table (-g option). Includes BUILDFT program to create frequency tables. Maximum value for -o option increased to 50000 from 256. Allows -o0 to suppress text display. Corrects a problem in parsing hex targets and allows single-digit hex characters (e.g., $A instead of $0A). Uses character frequency table in all searches unless wildcards are present in the search target. Includes 386-only version of FGREP.COM. Corrects a problem in earlier versions that sometimes caused FGREP to incorrectly report insufficent memory. Now requires DOS 3.0 or later. Version 1.72 ------------ Fixes problem with DOS 2.x, unable to read files. Version 1.71 ------------ Adds file lists. Adds file sharing support. Corrects two bugs in binary mode display: displaying data beyond end of file, and skipping bytes immediately after the target. Version 1.70 ------------ Adds binary search. Adds target concatenation (target+target). Cancels if no file specified and not redirected. Version 1.64 ------------ Bug fix release only: fix garbage in -M display from 1.63 Version 1.63 ------------ Distinguish between -M (path) and -m (no path) switches. -M/-m and -S now mutually exclusive. Allow search for literal '?' character via '\?'. Version 1.62 ------------ Added -M switch. Increased max length of lines ("slow" search) from 256 to 500. Version 1.61 ------------ Fixed a problem with pausing on > 255 hits (-P not specified). Version 1.60 ------------ Added -P switch. Fixed a problem with tab characters and -O switch. Version 1.59 ------------ Added -O switch. Altered -L operations to allow for line numbers > 65535. Line numbers now right justified in a 6-character field. Version 1.58 ------------ Fixed two problems that were causing endless loops in 1.55-1.57. Added -A switch. Version 1.57 ------------ Added -X switch. Versions 1.55/1.56 ----------------- "Fast" search algorithm added (thanks to Dave Angel for the idea and the shove). Fixed problems with redirected input. Forced -v (reVerse) search to show blank lines. Versions 1.50/1.51 ------------------ These versions contain no new features but are significantly faster than earlier versions. Standard (case-insensitive) searches run about 40% faster than 1.45 (which was 25-30% faster than 1.40). "Literal" searches (case-sensitive and spacing-sensitive) are highly optimized and may be as much as 70% faster than 1.45. Version 1.45 ------------ We found a few areas that could be made more efficient. This version can be as much as 25-30% faster than version 1.40. The -L (line numbers) option was added, and improvements made to parameter parsing such that delimiters are not always necessary. Copyright/License/Warranty -------------------------- This document and the program files FGREP.COM and BUILDFT.COM ("the software") are copyrighted by the author. If you are an individual, the copyright owner hereby licenses you to: use the software; make as many copies of the program and documentation as you wish; give such copies to anyone; and distribute the software and documentation via electronic means. There is no charge for any of the above. However, you are specifically prohibited from charging, or requesting donations, for any such copies, however made; and from distributing the software and/or documentation with commercial products without prior permission. An exception is granted to not-for-profit user's groups, which are authorized to charge a small fee (not to exceed $7) for materials, handling, postage, and general overhead. NO FOR-PROFIT ORGANIZATION IS AUTHORIZED TO CHARGE ANY AMOUNT FOR DISTRIBUTION OF COPIES OF THE SOFTWARE OR DOCUMENTATION, OR TO INCLUDE COPIES OF THE SOFTWARE OR DOCUMENTATION WITH SALES OF THEIR OWN PRODUCTS. THIS INCLUDES A SPECIFIC PROHIBITION AGAINST FOR-PROFIT ORGANIZATIONS DISTRIBUTING THE SOFTWARE, EITHER ALONE OR WITH OTHER SOFTWARE, AND CHARGING A "HANDLING" OR "MATERIALS" FEE OR ANY OTHER SUCH FEE FOR THE DISTRIBUTION. NO FOR-PROFIT ORGANIZATION IS AUTHORIZED TO INCLUDE THE SOFTWARE ON ANY MEDIA FOR WHICH MONEY IS CHARGED. PERIOD. Businesses, institutions, and governmental entities must obtain a specific license agreement from The Cove Software Group in order to use the software. No copy of the software may be distributed or given away without this document; and this notice must not be removed. There is no warranty of any kind, and the copyright owner is not liable for damages of any kind. By using this free software, you agree to this. The software and documentation are: Copyright (C) 1985-1995 by Christopher J. Dunford The Cove Software Group P.O. Box 1072 Columbia, Maryland 21044 Tel: (410) 992-9371 CompuServe: 76703,2002 Internet: 76703.2002@compuserve.com