Skip to content

Commit 1c6d785

Browse files
author
Chris Greenshields
committed
foamFind: script to find files in OpenFOAM and optionally process the contents
by printing their contents or lines which match a search string. Usage: ${0##*/} [OPTIONS] <filename> options: -a | -applications search for the file from the \$FOAM_APP directory -d | -dir <dir> specify search directory -f | -files find wmake 'files' file associated with searched file -h | -help help -i | -isearch <string> searches files for a <string>, case insensitive -m | -modules search for the file from the \$FOAM_MODULES directory -n | -numbers print line numbers with file output -o | -options find wmake 'options' file associated with searched file -p | -print print the file(s) -s | -search <string> searches files for a <string>, case sensitive -t | -tutorials search for the file from the \$FOAM_TUTORIALS directory Finds one or more files in OpenFOAM and optionally processes the contents by: + printing the file ('-print' option); + printing lines within the file matching a search string ('-search' option). With source code files, can locate the 'files' and 'options' files associated with their compilation using 'wmake'. By default, files are searched from the src (\$FOAM_SRC) directory. Alternatively the '-dir' option allows the user to specify the search directory The '-applications', '-modules' and '-tutorials' options specifically set the search path to the \$FOAM_APP, \$FOAM_MODULES and \$FOAM_TUTORIALS directories, respectively. Examples: foamFind -print wallHeatFlux.C | less + click space bar to scroll down + enter line number (after ":") to jump to line + enter "/text" to search for "text" (or any other string) foamFind -applications -isearch "momentumtransport" -options fluid.C foamFind -numbers -search laminar BirdCarreau.C
1 parent ed59ea4 commit 1c6d785

File tree

3 files changed

+568
-5
lines changed

3 files changed

+568
-5
lines changed

bin/foamFind

Lines changed: 388 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,388 @@
1+
#!/bin/sh
2+
#------------------------------------------------------------------------------
3+
# ========= |
4+
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5+
# \\ / O peration | Website: https://openfoam.org
6+
# \\ / A nd | Copyright (C) 2024 OpenFOAM Foundation
7+
# \\/ M anipulation |
8+
#------------------------------------------------------------------------------
9+
# License
10+
# This file is part of OpenFOAM.
11+
#
12+
# OpenFOAM is free software: you can redistribute it and/or modify it
13+
# under the terms of the GNU General Public License as published by
14+
# the Free Software Foundation, either version 3 of the License, or
15+
# (at your option) any later version.
16+
#
17+
# OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
18+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20+
# for more details.
21+
#
22+
# You should have received a copy of the GNU General Public License
23+
# along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24+
#
25+
# Script
26+
# foamFile
27+
#
28+
# Description
29+
# Finds one or more files in OpenFOAM and optionally processes the contents
30+
# by printing the file or lines matching a search string
31+
#
32+
#------------------------------------------------------------------------------
33+
usage () {
34+
cat <<USAGE
35+
36+
Usage: ${0##*/} [OPTIONS] <filename>
37+
options:
38+
-a | -applications search for the file from the \$FOAM_APP directory
39+
-d | -dir <dir> specify search directory
40+
-f | -files find wmake 'files' file associated with searched file
41+
-h | -help help
42+
-i | -isearch <string> searches files for a <string>, case insensitive
43+
-m | -modules search for the file from the \$FOAM_MODULES directory
44+
-n | -numbers print line numbers with file output
45+
-o | -options find wmake 'options' file associated with searched file
46+
-p | -print print the file(s)
47+
-s | -search <string> searches files for a <string>, case sensitive
48+
-t | -tutorials search for the file from the \$FOAM_TUTORIALS directory
49+
50+
Finds one or more files in OpenFOAM and optionally processes the contents by:
51+
+ printing the file ('-print' option);
52+
+ printing lines within the file matching a search string ('-search' option).
53+
54+
With source code files, can locate the 'files' and 'options' files associated
55+
with their compilation using 'wmake'.
56+
57+
By default, files are searched from the src (\$FOAM_SRC) directory.
58+
Alternatively the '-dir' option allows the user to specify the search directory
59+
The '-applications', '-modules' and '-tutorials' options specifically set the
60+
search path to the \$FOAM_APP, \$FOAM_MODULES and \$FOAM_TUTORIALS directories,
61+
respectively.
62+
63+
Examples:
64+
foamFind -print wallHeatFlux.C | less
65+
+ click space bar to scroll down
66+
+ enter line number (after ":") to jump to line
67+
+ enter "/text" to search for "text" (or any other string)
68+
69+
foamFind -applications -isearch "momentumtransport" -options fluid.C
70+
foamFind -numbers -search laminar BirdCarreau.C
71+
72+
USAGE
73+
}
74+
75+
error() {
76+
exec 1>&2
77+
while [ "$#" -ge 1 ]; do echo "$1"; shift; done
78+
usage
79+
exit 1
80+
}
81+
82+
findWmakeFiles () {
83+
_file="$1" ; shift
84+
_wmakeFiles="$*"
85+
86+
# Check if file is source code
87+
! file -b "$_file" | grep -Eq "C.*source" && \
88+
"'-$_filename' invalid, file is not source code" >&2 && \
89+
return 1
90+
91+
_files=""
92+
while true
93+
do
94+
_oldFile="$_file"
95+
_file="${_file%/*}"
96+
97+
# cannot contract the path further
98+
[ "$_oldFile" = "$_file" ] && break
99+
100+
# search for 'files' and/or 'options'
101+
[ -d "$_file" ] && \
102+
for _w in $_wmakeFiles
103+
do
104+
_files="$(echo "$_files" \
105+
"$(find "$_file" -name "$_w" -type f)" | xargs)"
106+
done
107+
108+
[ "$_files" ] && break
109+
done
110+
111+
! [ "$_files" ] && \
112+
error "no '$_filename' file found for '-files' or '-options'" >&2 && \
113+
return 1
114+
115+
echo "$_files"
116+
return 0
117+
}
118+
119+
nParams () {
120+
[ "$1" ] || return 1
121+
122+
echo "$1" | xargs | awk -F' ' '{print NF}'
123+
return 0
124+
}
125+
126+
selectFile () {
127+
_filename="$1"; shift
128+
_files="$*"
129+
_nFiles="$(nParams "$_files")"
130+
131+
# Return file if only one
132+
[ "$_nFiles" -eq 1 ] && echo "$_files" && exit 0
133+
134+
printf "Multiple files" >&2
135+
[ "$_filename" ] && printf " with name '%s'" "$_filename" >&2
136+
printf " found:\n" >&2
137+
138+
_i=1
139+
for _f in $_files
140+
do
141+
printf "%i) %s\n" "$_i" "$_f" >&2
142+
_i=$((_i + 1))
143+
done
144+
printf "Type ENTER to select all, or " >&2
145+
printf "enter file number (1-%s) for specific file: " \
146+
"$_nFiles" >&2
147+
148+
read -r _nFile
149+
150+
# Enter nothing
151+
[ -z "$_nFile" ] && echo "$_files" && return 0
152+
153+
# Check incorrect number
154+
! [ "$_nFile" -eq "$_nFile" ] 2>/dev/null && \
155+
echo "\"$_nFile\" is not a number" >&2 && \
156+
return 1
157+
{ [ "$_nFile" -lt 1 ] || [ "$_nFile" -gt "$_nFiles" ] ; } && \
158+
echo "\"$_nFile\" is not a number between 1 and $_nFiles" >&2 && \
159+
return 1
160+
161+
# Enter number corresponding to file
162+
# shellcheck disable=SC2086
163+
echo $_files | awk -v n="$_nFile" '{print $n}'
164+
return 0
165+
}
166+
167+
setFile () {
168+
_files="$1"
169+
_n="$2"
170+
echo "$_files" | xargs -n 1 | awk -v n="${_n}" 'NR==n'
171+
}
172+
173+
isSrcDir () {
174+
echo "$1" | grep -wqE "^($FOAM_SRC|$FOAM_APP)"
175+
}
176+
177+
listFiles () {
178+
_dir="$1"
179+
_filename="$2"
180+
_search="$3"
181+
_ins=""
182+
183+
[ "$4" = "on" ] && _ins="i"
184+
185+
# Specify code files if _dir is in $FOAM_SRC or $FOAM_APP
186+
_name="*"
187+
isSrcDir "$dir" && _name="*.[CHL]"
188+
[ "$_filename" ] && _name="$_filename"
189+
190+
[ "$_search" ] && \
191+
find "$_dir" -name "$_name" -type f -print0 | \
192+
xargs -0 grep -l$_ins "$search" && \
193+
return 0
194+
195+
# Remove "\n"
196+
find "$dir" -name "$filename" -type f -print0 | xargs -0
197+
}
198+
199+
grepFile () {
200+
_string="$1"
201+
_file="$2"
202+
_ins=""
203+
[ "$3" = "on" ] && _ins="i"
204+
_arg="$4"
205+
206+
# use $_arg for different cases: test, and with and without line numbers
207+
case "$_arg" in
208+
test)
209+
grep -q"$_ins" "$_string" "$_file"
210+
;;
211+
numbers)
212+
grep -hn"$_ins" "$_string" "$_file" | \
213+
awk '{
214+
split($0,f,":");
215+
sub(/^([^:]+:)/,"",$0);
216+
printf "%6i %s\n", f[1], $0
217+
}'
218+
;;
219+
*)
220+
grep -h"$_ins" "$_string" "$_file"
221+
;;
222+
esac
223+
}
224+
225+
dirError () {
226+
cat<<EOF
227+
Search directory specified with more than one option from '-applications', '-dir',
228+
'-modules' and '-tutorials'. Please specify only one of these options.
229+
EOF
230+
}
231+
232+
searchError () {
233+
cat<<EOF
234+
The '-search' and '-isearch' options are both be specified.
235+
Please specify only one of these options, either '-isearch' for a
236+
case-insensitive search or '-search' for case-sensitive.
237+
EOF
238+
}
239+
240+
printError () {
241+
cat<<EOF
242+
The '-search/-isearch' and '-print' options are both be specified.
243+
Please specify only one of these options, either '-search/-isearch' to print
244+
lines of files(s) matching an expression, or '-print' for the entire file(s).
245+
EOF
246+
}
247+
248+
dir=""
249+
print=""
250+
wmakeFiles=""
251+
search=""
252+
insensitive=""
253+
numbers=""
254+
filename=""
255+
256+
while [ "$#" -gt 0 ]
257+
do
258+
case "$1" in
259+
-a | -applications)
260+
[ "$dir" ] && error "$(dirError)"
261+
dir="$FOAM_APP"
262+
shift
263+
;;
264+
-d | -dir)
265+
[ "$dir" ] && error "$(dirError)"
266+
[ "$#" -ge 2 ] || error "'$1' option requires an argument"
267+
[ -d "$2" ] || error "'$2' argument to '-dir' option is not a directory"
268+
# shellcheck disable=SC2164
269+
dir="$(cd "$2"; pwd)"
270+
# Check $dir is in OpenFOAM
271+
! echo "$dir" | grep -wq "^$WM_PROJECT_DIR" && \
272+
error "Specified directory '$dir' is not in OpenFOAM installation"
273+
shift 2
274+
;;
275+
-f | -files)
276+
wmakeFiles="$wmakeFiles files"
277+
shift
278+
;;
279+
-h | -help)
280+
usage
281+
;;
282+
-i | -isearch)
283+
[ "$#" -ge 2 ] || error "'$1' option requires an argument"
284+
[ "$insensitive" ] && error "$(searchError)"
285+
[ "$print" ] && error "$(printError)"
286+
search="$2"
287+
insensitive=on
288+
shift 2
289+
;;
290+
-m | -modules)
291+
[ "$dir" ] && error "$(dirError)"
292+
dir="$FOAM_MODULES"
293+
shift
294+
;;
295+
-n | -numbers)
296+
numbers="numbers" # flag for line numbers in cat or grep
297+
shift
298+
;;
299+
-o | -options)
300+
wmakeFiles="$wmakeFiles options"
301+
shift
302+
;;
303+
-p | -print)
304+
[ "$insensitive" ] && error "$(printError)"
305+
print="yes"
306+
shift
307+
;;
308+
-s | -search)
309+
[ "$#" -ge 2 ] || error "'$1' option requires an argument"
310+
[ "$insensitive" ] && error "$(searchError)"
311+
[ "$print" ] && error "$(printError)"
312+
search="$2"
313+
insensitive=off
314+
shift 2
315+
;;
316+
-t | -tutorials)
317+
[ "$dir" ] && error "$(dirError)"
318+
dir="$FOAM_TUTORIALS"
319+
shift
320+
;;
321+
-*)
322+
error "Invalid option '$1'"
323+
;;
324+
*)
325+
# If filename is already set, then exit
326+
[ "$filename" ] && error "Arguments specified ($#) =/= 1"
327+
filename="$1"
328+
shift
329+
;;
330+
esac
331+
done
332+
333+
# Default search directory if not specified
334+
[ "$dir" ] || dir="$FOAM_SRC"
335+
336+
# Disallow '-files' and '-options' if search directory does not include source code
337+
[ "$wmakeFiles" ] && ! isSrcDir "$dir" && \
338+
error "With search directory '$dir' (not source code)," \
339+
"cannot use '-files' or '-options'"
340+
341+
# Check number of arguments
342+
[ "$#" -eq 0 ] || error "Arguments specified =/= 1 (optional)"
343+
344+
# If filename is not set, check search string is specified
345+
! [ "$filename" ] && ! [ "$search" ] && \
346+
error "<filename> can only be omitted if a search string is specified" \
347+
"with the '-search' option"
348+
349+
# If '-files' or '-options' is selected, ensure <filename> is set
350+
! [ "$filename" ] && [ "$wmakeFiles" ] && \
351+
error "With '-files' or '-options', <filename> must be specified"
352+
353+
# Find files
354+
files="$(listFiles "$dir" "$filename" "$search" "$insensitive")"
355+
356+
# Ensure there is at least one file
357+
nParams "$files" > /dev/null || error "No file '$filename' found in '$dir'"
358+
359+
# Select files when more than one is found
360+
files="$(selectFile "$filename" "$files")" || error
361+
362+
# With '-files' and/or '-options', reuse file variable as the file
363+
[ "$wmakeFiles" ] && \
364+
[ "$(nParams "$files")" -ne 1 ] && \
365+
error "With '-files' or '-options', a single <filename> must be specified"
366+
367+
[ "$wmakeFiles" ] &&
368+
! files="$(findWmakeFiles "$files" "$wmakeFiles")" && error
369+
370+
# Output
371+
for f in $files
372+
do
373+
printf "\nFile: %s\n" "$f"
374+
375+
# Printing entire files
376+
[ "$print" ] && \
377+
printf ">>>\n" && \
378+
{ [ "$numbers" ] && cat -n "$f" || cat "$f" ; } && \
379+
printf "<<<\n"
380+
381+
# Printing lines matching strings
382+
[ "$search" ] || continue
383+
! grepFile "$search" "$f" "$insensitive" test && \
384+
echo "Search: no match" && continue
385+
printf ">>>\n"
386+
grepFile "$search" "$f" "$insensitive" "$numbers"
387+
printf "<<<\n"
388+
done

0 commit comments

Comments
 (0)