1FindLib(3) User Contributed Perl Documentation FindLib(3)
2
3
4
6 File::FindLib - Find and use a file/dir from a directory above your
7 script file
8
10 use File::FindLib 'lib';
11
12 Or
13
14 use File::FindLib 'lib/MyCorp/Setup.pm';
15
17 File::FindLib starts in the directory where your script (or library) is
18 located and looks for the file or directory whose name you pass in. If
19 it isn't found, then FindLib looks in the parent directory and
20 continues moving up parent directories until it finds it or until there
21 is not another parent directory.
22
23 If it finds the named path and it is a directory, then it prepends it
24 to @INC. That is,
25
26 use File::FindLib 'lib';
27
28 is roughly equivalent to:
29
30 use File::Basename qw< dirname >;
31 use lib dirname(__FILE__) . '/../../../lib';
32
33 except you don't have to know how many '../'s to include and it adjusts
34 if __FILE__ is a symbolic link.
35
36 If it finds the named path and it is a file, then it loads the Perl
37 code stored in that file. That is,
38
39 use File::FindLib 'lib/MyCorp/Setup.pm';
40
41 is roughly equivalent to:
42
43 use File::Basename qw< dirname >;
44 BEGIN {
45 require dirname(__FILE__) . '/../../../lib/MyCorp/Setup.pm';
46 }
47
48 except you don't have to know how many '../'s to include (and it
49 adjusts if __FILE__ is a symbolic link).
50
51 MOTIVATION
52 It is common to have a software product that gets deployed as a tree of
53 directories containing commands (scripts) and/or test scripts in the
54 deployment that need to find Perl libraries that are part of the
55 deployment.
56
57 By including File::FindLib in your standard Perl deployment, you can
58 include one or more custom initialization or boot-strap modules in each
59 of your software deployments and easily load one by pasting one short
60 line into each script. The custom module would likely add some
61 directories to @INC so that the script can then just load any modules
62 that were included in the deployment.
63
64 For example, you might have a deployment structure that looks like:
65
66 bin/init
67 ...
68 db/bin/dump
69 ...
70 lib/MyCorp/Setup.pm
71 lib/MyCorp/Widget.pm
72 lib/MyCorp/Widget/Connect.pm
73 ...
74 t/TestEnv.pm
75 t/itPing.t
76 t/itTimeOut.t
77 t/MyCorp/Widget/basic.t
78 ...
79 t/MyCorp/Widget/Connect/retry.t
80 ...
81 t/testlib/MyTest.pm
82 ...
83
84 And your various Perl scripts like bin/init and db/bin/dump might start
85 with:
86
87 use File::FindLib 'lib/MyCorp/Setup.pm';
88 use MyCorp::Widget;
89
90 And Setup.pm might start with:
91
92 package MyCorp::Setup;
93 use File::FindLib 'lib';
94
95 While your various test scripts might start with:
96
97 use File::FindLib 't/TestEnv.pm';
98 use MyTest qw< plan ok >;
99
100 where TestEnv.pm might start with:
101
102 package TestEnv;
103 use File::FindLib 'testlib'; # Find modules in $repo/t/testlib/
104 use File::FindLib 'lib'; # Find modules in $repo/lib/
105
106 And you don't have to worry about having to update a script if it gets
107 moved to a different point in the deployment directory tree.
108
109 SYMBOLIC LINKS
110 If the calling script/library was loaded via a symbolic link (if "-l
111 __FILE__" is true inside the calling code), then File::FindLib will
112 start looking from where that symbolic link points. If it points at
113 another symbolic link or if any of the parent directories are symbolic
114 links, then File::FindLib will ignore this fact.
115
116 So, if we have the following symbolic links:
117
118 /etc/init.d/widget -> /site/mycorp/widget/bin/init-main
119 /site/mycorp/widget/bin/init-main -> ../util/admin/init
120 /site/mycorp/widget/ -> ../dist/widget/current/
121 /site/mycorp/dist/widget/current/ -> 2011-12-01/
122 /site/mycorp/dist/widget/2011-12-01 -> v1.042_037/
123 /site/mycorp/ -> /export/site/mycorp/
124 /site -> /export/var/site
125
126 And the following command produces the following output:
127
128 $ head -2 /etc/init.d/widget
129 #!/usr/bin/perl
130 use File::FindLib 'lib/Setup.pm';
131 $
132
133 Then File::FindLib will do:
134
135 See that it was called from /etc/init.d/widget.
136 See that this is a symbolic link.
137 Act like it was called from /site/mycorp/widget/bin/init-main.
138 (Ignore that this is another symbolic link.)
139 Search for:
140 /site/mycorp/widget/bin/lib/Setup.pm
141 /site/mycorp/widget/lib/Setup.pm
142 /site/mycorp/lib/Setup.pm
143 /site/lib/Setup.pm
144 /lib/Setup.pm
145
146 Only the first symbolic link that we mentioned is noticed.
147
148 This would be unfortunate if you also have the symbolic link:
149
150 /etc/rc2.d/S99widget -> ../init.d/widget
151
152 Since running that command would cause the following searches:
153
154 /etc/init.d/lib/Setup.pm
155 /etc/lib/Setup.pm
156 /lib/Setup.pm
157
158 If you instead made a hard link:
159
160 # ln /etc/init.d/widget /etc/rc2.d/S99widget
161
162 then /etc/init.d/widget would also be a symbolic link to
163 /site/mycorp/widget/bin/init-main which would surely work better.
164
165 So future versions of File::FindLib may notice more cases of symbolic
166 links or provide options for controlling which symbolic links to
167 notice.
168
169 %INC
170 The code:
171
172 use File::FindLib 'lib/MyCorp/Setup.pm';
173
174 is more accurately approximated as:
175
176 use File::Basename qw< dirname >;
177 BEGIN {
178 my $path= dirname(__FILE__) . '/../../../lib/MyCorp/Setup.pm';
179 require $path;
180 $INC{'MyCorp/Setup.pm'} ||= $INC{$path};
181 }
182
183 The setting of $INC{'MyCorp/Setup.pm'} is so that:
184
185 use File::FindLib 'lib/MyCorp/Setup.pm';
186 ...
187 use MyCorp::Setup;
188
189 doesn't try to load the MyCorp::Setup module twice.
190
191 Though, this is only done if lib/MyCorp/Setup.pm defines a
192 MyCorp::Setup package... and $INC{'MyCorp/Setup.pm'} isn't already set
193 and there is no lib::MyCorp::Setup package defined. See the source
194 code if you have to know every detail of the heuristics used, though
195 misfires are unlikely (especially since module names are usually
196 capitalized while library subdirectory names usually are not).
197
198 Even this problem case is unlikely and the consequences of loading the
199 same module twice are often just harmless warnings, if that.
200
201 So this detail will not matter most of the time.
202
204 I'd like to support a more powerful interface. For example:
205
206 use File::FindLib(
207 -from => __FILE__,
208 -upto => 'ReleaseVersion.txt',
209 -inc => 'custom/lib', # Like: use lib ...
210 +inc => 'lib', # Like: push @INC, ...
211 -load => 'initEnv.pl', # Like: require ...
212 \my $DataDir => 'custom/data', # Sets $DataDir to full path
213 );
214
215 But adding such an interface should not interfere with the one-argument
216 interface already implemented.
217
219 Author: Tye McQueen, http://perlmonks.org/?node=tye
220
222 Lake Missoula
223
224
225
226perl v5.36.0 2023-01-20 FindLib(3)