1
2(********************************************************************)
3(*                                                                  *)
4(*  find7.sd7     Utility to search for files and file contents.    *)
5(*  Copyright (C) 2016  Thomas Mertes                               *)
6(*                                                                  *)
7(*  This program is free software; you can redistribute it and/or   *)
8(*  modify it under the terms of the GNU General Public License as  *)
9(*  published by the Free Software Foundation; either version 2 of  *)
10(*  the License, or (at your option) any later version.             *)
11(*                                                                  *)
12(*  This program is distributed in the hope that it will be useful, *)
13(*  but WITHOUT ANY WARRANTY; without even the implied warranty of  *)
14(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   *)
15(*  GNU General Public License for more details.                    *)
16(*                                                                  *)
17(*  You should have received a copy of the GNU General Public       *)
18(*  License along with this program; if not, write to the           *)
19(*  Free Software Foundation, Inc., 51 Franklin Street,             *)
20(*  Fifth Floor, Boston, MA  02110-1301, USA.                       *)
21(*                                                                  *)
22(********************************************************************)
23
24
25$ include "seed7_05.s7i";
26  include "osfiles.s7i";
27  include "console.s7i";
28  include "getf.s7i";
29
30
31const proc: writeMatchingLines (in string: filePath, in string: stringSearched) is func
32  local
33    var string: content is "";
34    var integer: pos is 0;
35    var integer: startPos is 0;
36    var integer: endPos is 0;
37  begin
38    content := getf(filePath);
39    pos := pos(content, stringSearched);
40    if pos <> 0 then
41      writeln(filePath <& ":");
42      startPos := rpos(content, '\n', pos);
43      incr(startPos);
44      endPos := pos(content, '\n', pos);
45      if endPos = 0 then
46        endPos := length(content);
47      else
48        decr(endPos);
49      end if;
50      writeln(content[startPos .. endPos]);
51    end if;
52  end func;
53
54
55const proc: searchDir (in string: dirPath,
56    in string: partOfFileName, in string: stringSearched) is func
57  local
58    var array string: dirElements is 0 times "";
59    var string: fileName is "";
60    var string: filePath is "";
61  begin
62    block
63      dirElements := readDir(dirPath);
64    exception
65      catch FILE_ERROR:
66        writeln(" *** Cannot read directory " <& dirPath);
67    end block;
68    for fileName range dirElements do
69      if dirPath = "/" then
70        filePath := "/" & fileName;
71      else
72        filePath := dirPath & "/" & fileName;
73      end if;
74      if partOfFileName = "" or
75          pos(lower(fileName), partOfFileName) <> 0 then
76        if stringSearched = "" then
77          writeln(filePath);
78        else
79          writeMatchingLines(filePath, stringSearched);
80        end if;
81      end if;
82      case fileType(filePath) of
83        when {FILE_DIR}:
84          if fileTypeSL(filePath) = FILE_SYMLINK and
85              startsWith(dirPath, toAbsPath(dirPath, readLink(filePath))) then
86            writeln(" *** Symbolic link loop " <& filePath);
87          else
88            searchDir(filePath, partOfFileName, stringSearched);
89          end if;
90        when {FILE_SYMLINK}:
91          writeln(" *** Cannot follow symbolic link " <& filePath);
92      end case;
93    end for;
94  end func;
95
96
97const proc: main is func
98  local
99    var string: dirPath is "";
100    var string: partOfFileName is "";
101    var string: stringSearched is "";
102  begin
103    OUT := STD_CONSOLE;
104    if length(argv(PROGRAM)) < 2 then
105      writeln("Find7 Version 1.0 - Utility to search for files and file contents.");
106      writeln("Copyright (C) 2016 Thomas Mertes");
107      writeln("This is free software; see the source for copying conditions.  There is NO");
108      writeln("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
109      writeln("Find7 is written in the Seed7 programming language");
110      writeln("Homepage: http://seed7.sourceforge.net");
111      writeln;
112      writeln("usage: find7 directory partOfFileName [stringSearched]");
113      writeln;
114      writeln("Examples:");
115      writeln("  find7 . .sd7");
116      writeln("     Search for files with a name that contains .sd7 in the current");
117      writeln("     working directory and its subdirectories.");
118      writeln("  find7 ../lib .s7i decompose");
119      writeln("     Search if .s7i files in the ../lib directory contain the word");
120      writeln("     decompose.");
121      writeln("  find7 ../doc \"\" \"Seed7 program\"");
122      writeln("     Search if any file in the ../doc directory contains the phrase");
123      writeln("     Seed7 program.");
124    else
125      dirPath := convDosPath(argv(PROGRAM)[1]);
126      partOfFileName := lower(argv(PROGRAM)[2]);
127      if length(argv(PROGRAM)) >= 3 then
128        stringSearched := argv(PROGRAM)[3];
129      end if;
130      searchDir(dirPath, partOfFileName, stringSearched);
131    end if;
132  end func;
133