aboutsummaryrefslogtreecommitdiff
blob: 740317ad13f471de172eb7cc211afe76f6971701 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
<?xml version="1.0" encoding="UTF-8"?>
<devbook self="tools-reference/find/">
<chapter>
<title><c>find</c>  finding files</title>
<body>

<p>
The <c>find</c> utility can be used to search for and perform commands upon
groups of files matching a given set of criteria. The basic usage is
<c>find path rules</c>.
</p>

<p>
For portability purposes, <b>always</b> specify a path. Do not rely
upon <c>find</c> defaulting to the current working directory if no
path is provided.
</p>

<p>
Useful rules include:
</p>

<table>
  <tr>
    <th>Rule</th>
    <th>Effect</th>
    <th>POSIX?</th>
  </tr>
  <tr>
    <ti><c>-name "blah"</c></ti>
    <ti>
      Only find files named <c>blah</c>. The <c>*</c> and <c>?</c>
      wildcards may be used but should be quoted as in <c>-name 'blah*'</c>.
    </ti>
    <ti>yes</ti>
  </tr>
    <tr>
    <ti><c>\! -name "blah"</c></ti>
    <ti>
      Only find files not named <c>blah</c>.
    </ti>
    <ti>yes</ti>
  </tr>
  <tr>
    <ti><c>-type f</c></ti>
    <ti>Find only regular files, not directories.</ti>
    <ti>yes</ti>
  </tr>
  <tr>
    <ti><c>-type d</c></ti>
    <ti>Find only directories.</ti>
    <ti>yes</ti>
  </tr>
  <tr>
    <ti><c>-type l</c></ti>
    <ti>Find only symbolic links.</ti>
    <ti>yes</ti>
  </tr>
  <tr>
    <ti><c>-user foo</c></ti>
    <ti>
      Find only files belonging to user <c>foo</c>. It is best to use
      named users rather than numeric UIDs. In particular, <c>root</c>
      may not be UID 0 on some systems.
    </ti>
    <ti>yes</ti>
  </tr>
  <tr>
    <ti><c>-group foo</c></ti>
    <ti>
      Find only files belonging to group <c>foo</c>. It is best to use
      named groups rather than numeric GIDs.
    </ti>
    <ti>yes</ti>
  </tr>
  <tr>
    <ti><c>-maxdepth 3</c></ti>
    <ti>
     Only descend 3 levels into subdirectories.
     <c>-maxdepth 1</c> will ignore all subdirectories of the specified path.
    </ti>
    <ti>no, GNU and BSD</ti>
  </tr>
  <tr>
    <ti><c>-mindepth 2</c></ti>
    <ti>
     Ignore the first 2 directory levels before a match occurs.
     <c>-mindepth 1</c> will process all files except the command line arguments.
    </ti>
    <ti>no, GNU and BSD</ti>
  </tr>
  <tr>
    <ti><c>-exec foo '{}'</c></ti>
    <ti>
     Execute a command. <c>{}</c> is replaced by the name of the
     current matched file. See examples below.
    </ti>
    <ti>yes</ti>
  </tr>
  <tr>
    <ti><c>-execdir foo '{}'</c></ti>
    <ti>
     Same as <c>-exec</c> but runs the command from within the basedir
     of the match.
    </ti>
    <ti>no, GNU and BSD</ti>
  </tr>
    <tr>
    <ti><c>-delete</c></ti>
    <ti>
     Delete the match.
    </ti>
    <ti>no, GNU and FBSD</ti>
  </tr>
  <tr>
    <ti><c>-print0</c></ti>
    <ti>
      Separate file names by a NUL character instead of a newline in
      the output. This is useful for guarding against files which may
      include a newline in their names.
    </ti>
    <ti>no, GNU and FBSD</ti>
  </tr>
</table>

<note>
EAPI&gt;=5 assumes GNU find, so it is safe to use GNU extensions in
ebuild context for those EAPIs.
</note>

<p>
By default, <c>find</c> will echo a list of matching files to the
standard output separated by newlines. It can be combined with a
<c>for</c> loop for a small number of files with no weird characters
and spaces in their names:
</p>

<codesample lang="ebuild">
for f in $(find "${S}" -type f) ; do
	einfo "Doing unholy things to ${f}"
done
</codesample>

<p>
The above loop may cause issues with files containing special
characters in their names. A better way is to run <c>find</c> with the
<c>-print0</c> option in a <c>while</c> loop (note the options passed
to <c>while</c> and <c>read</c> for changing the delimiter):
</p>

<codesample lang="ebuild">
while IFS="" read -d $'\0' -r f ; do
	einfo "Calling down holy vengance upon ${f}"
done &lt; &lt;(find "${S}" -type f -print0)
</codesample>

<p>
As an alternative you can use the <c>-exec</c> argument. Be careful
with escaping to ensure that <c>bash</c> doesn't gobble up the special
characters:
</p>

<codesample lang="ebuild">
find "${S}" -name '*.data' -exec mv '{}' "${S}/data/" \;
</codesample>

<p>
When <c>-exec</c> is terminated by a <c>;</c> character
(needs escaping or quoting) then the command line is built separately
for every match.
If it is terminated by a <c>+</c> character then the command line is
built by appending each selected file name at the end.
</p>

<p>
The syntax below is useful if the command you want to run accepts multiple
arguments such as <c>doins</c> and is more efficient in that case:
</p>

<codesample lang="ebuild">
find "${S}" -name '*.so*' -exec doexe '{}' +
</codesample>

<p>
Find also supports negative matches:
</p>

<codesample lang="ebuild">
find "${S}/bundled-libs" \! -name 'libbass.so' -delete
</codesample>

<p>
This will delete all files in the "bundled-libs" folder except "libbass.so".
Make sure you always escape the <c>!</c> character, so it's not
interpreted by the shell.
</p>

<warning>
The <c>-exec</c> argument has security issues, because of
<uri link="https://www.gnu.org/software/findutils/manual/html_mono/find.html#Race-Conditions-with-_002dexec">race conditions</uri>
(this is also true for <c>find . -print0 | xargs ...</c> constructs).
This should not be a problem in ebuild context, because directories
typically aren't writeable by random users. However you should
consider <c>-execdir</c> as an alternative approach which runs the
command from inside the basedir of the match (note that <c>-execdir</c>
is not POSIX, see the table).
</warning>

<p>
See <c>find(1)</c> and
<uri link="https://pubs.opengroup.org/onlinepubs/9699919799/utilities/find.html">
IEEE Std 1003.1-2017-find</uri> for further details and examples.
</p>

</body>
</chapter>
</devbook>