… | |
… | |
16 | -s, --stat call stat on every entry, to get stat data into cache |
16 | -s, --stat call stat on every entry, to get stat data into cache |
17 | -d, --dirs only list dirs |
17 | -d, --dirs only list dirs |
18 | -f, --files only list files |
18 | -f, --files only list files |
19 | -p, --progress regularly print progress to stderr |
19 | -p, --progress regularly print progress to stderr |
20 | --sync open/fsync/close every entry |
20 | --sync open/fsync/close every entry |
21 | -g, --grep=RE only list files that match the gibven perl RegEx |
21 | -g, --grep=RE only list files that match the given perl RegEx |
22 | |
22 | |
23 | =head1 DESCRIPTION |
23 | =head1 DESCRIPTION |
24 | |
24 | |
25 | The F<treescan> command scans directories and their contents |
25 | The F<treescan> command scans directories and their contents |
26 | recursively. By default it lists all files and directories (with trailing |
26 | recursively. By default it lists all files and directories (with trailing |
… | |
… | |
50 | |
50 | |
51 | Normally, F<treescan> will use heuristics to avoid most C<stat> calls, |
51 | Normally, F<treescan> will use heuristics to avoid most C<stat> calls, |
52 | which is what makes it so fast. This option forces it to C<stat> every file. |
52 | which is what makes it so fast. This option forces it to C<stat> every file. |
53 | |
53 | |
54 | This is only useful for the side effect of pulling the C<stat> data into |
54 | This is only useful for the side effect of pulling the C<stat> data into |
55 | the cache. If your disk cache is big enough, it will be filled with file |
55 | the cache. If your disk cache is big enough, it will be filled with |
56 | metadata after F<treescan> is done, which can speed up subsequent commands |
56 | file meta data after F<treescan> is done, which can speed up subsequent |
57 | considerably. Often, you can run F<treescan> in parallel with other |
57 | commands considerably. Often, you can run F<treescan> in parallel with |
58 | directory-scanning programs to speed them up. |
58 | other directory-scanning programs to speed them up. |
59 | |
59 | |
60 | =item -d, --dirs |
60 | =item -d, --dirs |
61 | |
61 | |
62 | Only lists directories, not file paths. This is useful if you quickly want |
62 | Only lists directories, not file paths. This is useful if you quickly want |
63 | a list of directories and their subdirectories. |
63 | a list of directories and their subdirectories. |
64 | |
64 | |
65 | =item -f, --files |
65 | =item -f, --files |
66 | |
66 | |
67 | Only list files, not directories. This is useful if you want to coperate |
67 | Only list files, not directories. This is useful if you want to operate on |
68 | on all files in a hierarchy, and the directories would ony get in the way. |
68 | all files in a hierarchy, and the directories would ony get in the way. |
69 | |
69 | |
70 | =item -p, --progress |
70 | =item -p, --progress |
71 | |
71 | |
72 | Regularly print some progress information to standard error. This is |
72 | Regularly print some progress information to standard error. This is |
73 | useful to get some progress information on long running tasks. Since |
73 | useful to get some progress information on long running tasks. Since |
… | |
… | |
131 | ); |
131 | ); |
132 | } |
132 | } |
133 | |
133 | |
134 | @ARGV = "." unless @ARGV; |
134 | @ARGV = "." unless @ARGV; |
135 | |
135 | |
|
|
136 | my @todo; # list of dirs/files still left to scan |
|
|
137 | |
136 | $opt_grep &&= qr{$opt_grep}s; |
138 | $opt_grep &&= qr{$opt_grep}s; |
137 | |
139 | |
138 | my ($n_dirs, $n_files, $n_stats) = (0, 0, 0); |
140 | my ($n_dirs, $n_files, $n_stats) = (0, 0, 0); |
139 | my ($n_last, $n_start) = (Time::HiRes::time) x 2; |
141 | my ($n_last, $n_start) = (Time::HiRes::time) x 2; |
140 | |
142 | |
… | |
… | |
195 | aio_pathsync [$wd, $_] for @$files; |
197 | aio_pathsync [$wd, $_] for @$files; |
196 | aio_pathsync $wd; |
198 | aio_pathsync $wd; |
197 | }; |
199 | }; |
198 | } |
200 | } |
199 | |
201 | |
200 | &scan ("$path$_") for @$dirs; |
202 | push @todo, "$path$_" |
|
|
203 | for sort { $b cmp $a } @$dirs; |
201 | }; |
204 | }; |
202 | } |
205 | } |
203 | |
206 | |
204 | IO::AIO::max_outstanding 100; # two fds per directory, so limit accordingly |
207 | IO::AIO::max_outstanding 100; # two fds per directory, so limit accordingly |
205 | IO::AIO::min_parallel 20; |
208 | IO::AIO::min_parallel 20; |
206 | |
209 | |
207 | for my $seed (@ARGV) { |
210 | @todo = reverse @ARGV; |
|
|
211 | |
|
|
212 | while () { |
|
|
213 | if (@todo) { |
|
|
214 | my $seed = pop @todo; |
208 | $seed =~ s/\/+$//; |
215 | $seed =~ s/\/+$//; |
209 | aio_lstat "$seed/.", sub { |
216 | aio_lstat "$seed/.", sub { |
210 | if ($_[0]) { |
217 | if ($_[0]) { |
211 | print STDERR "$seed: $!\n"; |
218 | print STDERR "$seed: $!\n"; |
212 | } elsif (-d _) { |
219 | } elsif (-d _) { |
213 | scan $seed; |
220 | scan $seed; |
214 | } else { |
221 | } else { |
215 | printfn "", $seed, "/"; |
222 | printfn "", $seed, "/"; |
|
|
223 | } |
216 | } |
224 | }; |
|
|
225 | } else { |
|
|
226 | IO::AIO::poll_wait; |
217 | }; |
227 | } |
218 | } |
|
|
219 | |
228 | |
220 | IO::AIO::flush; |
229 | last unless IO::AIO::nreqs; |
221 | |
230 | |
|
|
231 | IO::AIO::poll_cb; |
|
|
232 | } |
|
|
233 | |