ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/IO-AIO/bin/treescan
(Generate patch)

Comparing IO-AIO/bin/treescan (file contents):
Revision 1.16 by root, Sat Jan 25 00:15:52 2014 UTC vs.
Revision 1.17 by root, Sun Nov 13 16:19:31 2016 UTC

1#!/opt/bin/perl 1#!/opt/bin/perl
2 2
3# inspired by treescan by Jamie Lokier <jamie@imbolc.ucc.ie> 3# inspired by treescan by Jamie Lokier <jamie@imbolc.ucc.ie>
4# about 40% faster than the original version (on my fs and raid :) 4# about 40% faster than the original version (on my fs and raid :)
5
6=head1 NAME
7
8treescan - scan directory trees, list dirs/files, stat, sync, grep
9
10=head1 SYNOPSIS
11
12 treescan [OPTION...] [PATH...]
13
14 -q, --quiet do not print list of files/directories
15 -0, --print0 use null character instead of newline to separate names
16 -s, --stat call stat on every entry, to get stat data into cache
17 -d, --dirs only list dirs
18 -f, --files only list files
19 -p, --progress regularly print progress to stderr
20 --sync open/fsync/close every entry
21 -g, --grep=RE only list files that match the gibven perl RegEx
22
23=head1 DESCRIPTION
24
25The F<treescan> command scans directories and their contents
26recursively. By default it lists all files and directories (with trailing
27C</>), but it can optionally do various other things.
28
29If no paths are given, F<treescan> will use C<.>, the current directory.
30
31=head2 OPTIONS
32
33=over 4
34
35=item -q, --quiet
36
37By default, F<treescan> prints the full paths of all directories or files
38it finds. This option disables printing of filenames completely. This is
39useful if you want to run F<treescan> solely for its side effects, such as
40pulling C<stat> data into memory.
41
42=item -0, --print0
43
44Instead of using newlines, use null characters after each filename. This
45is useful to avoid quoting problems when piping the result into other
46programs (for example, GNU F<grep>, F<xargs> and so on all have options to
47deal with this).
48
49=item -s, --stat
50
51Normally, F<treescan> will use heuristics to avoid most C<stat> calls,
52which is what makes it so fast. This option forces it to C<stat> every file.
53
54This is only useful for the side effect of pulling the C<stat> data into
55the cache. If your disk cache is big enough, it will be filled with file
56metadata after F<treescan> is done, which can speed up subsequent commands
57considerably. Often, you can run F<treescan> in parallel with other
58directory-scanning programs to speed them up.
59
60=item -d, --dirs
61
62Only lists directories, not file paths. This is useful if you quickly want
63a list of directories and their subdirectories.
64
65=item -f, --files
66
67Only list files, not directories. This is useful if you want to coperate
68on all files in a hierarchy, and the directories would ony get in the way.
69
70=item -p, --progress
71
72Regularly print some progress information to standard error. This is
73useful to get some progress information on long running tasks. Since
74the progress is printed to standard error, you can pipe the output of
75F<treescan> into other programs as usual.
76
77=item --sync
78
79The C<--sync> option can be used to make sure all the files/dirs in a tree
80are sync'ed to disk. For example this could be useful after unpacking an
81archive, to make sure the files hit the disk before deleting the archive
82file itself.
83
84=item -g, --grep=RE
85
86This applies a perl regular expression (see the L<perlre> manpage) to all paths that would normally be printed
87and will only print matching paths.
88
89The regular expression uses an C</s> (single line) modifier by default, so
90newlines are matched by C<.>.
91
92=back
93
94=head1 AUTHOR
95
96 Marc Lehmann <schmorp@schmorp.de>
97 http://home.schmorp.de/
98
99=cut
5 100
6use common::sense; 101use common::sense;
7use Getopt::Long; 102use Getopt::Long;
8use Time::HiRes (); 103use Time::HiRes ();
9use IO::AIO; 104use IO::AIO;
10 105
11our $VERSION = $IO::AIO::VERSION; 106our $VERSION = $IO::AIO::VERSION;
12 107
13Getopt::Long::Configure ("bundling", "no_ignore_case", "require_order", "auto_help", "auto_version"); 108Getopt::Long::Configure ("bundling", "no_ignore_case", "require_order", "auto_help", "auto_version");
14 109
15my ($opt_silent, $opt_print0, $opt_stat, $opt_nodirs, 110my ($opt_silent, $opt_print0, $opt_stat, $opt_nodirs, $opt_help,
16 $opt_nofiles, $opt_grep, $opt_progress); 111 $opt_nofiles, $opt_grep, $opt_progress, $opt_sync);
17 112
18GetOptions 113GetOptions
19 "quiet|q" => \$opt_silent, 114 "quiet|q" => \$opt_silent,
20 "print0|0" => \$opt_print0, 115 "print0|0" => \$opt_print0,
21 "stat|s" => \$opt_stat, 116 "stat|s" => \$opt_stat,
22 "dirs|d" => \$opt_nofiles, 117 "dirs|d" => \$opt_nofiles,
23 "files|f" => \$opt_nodirs, 118 "files|f" => \$opt_nodirs,
24 "grep|g=s" => \$opt_grep, 119 "grep|g=s" => \$opt_grep,
25 "progress|p" => \$opt_progress, 120 "progress|p" => \$opt_progress,
121 "sync" => \$opt_sync,
122 "help" => \$opt_help,
26 or die "Usage: try $0 --help"; 123 or die "Usage: try $0 --help";
124
125if ($opt_help) {
126 require Pod::Usage;
127
128 Pod::Usage::pod2usage (
129 -verbose => 1,
130 -exitval => 0,
131 );
132}
27 133
28@ARGV = "." unless @ARGV; 134@ARGV = "." unless @ARGV;
29 135
30$opt_grep &&= qr{$opt_grep}s; 136$opt_grep &&= qr{$opt_grep}s;
31 137
57 $n_last = Time::HiRes::time; 163 $n_last = Time::HiRes::time;
58 my $d = $n_last - $n_start; 164 my $d = $n_last - $n_start;
59 printf STDERR "\r%d dirs (%g/s) %d files (%g/s) %d stats (%g/s) ", 165 printf STDERR "\r%d dirs (%g/s) %d files (%g/s) %d stats (%g/s) ",
60 $n_dirs, $n_dirs / $d, 166 $n_dirs, $n_dirs / $d,
61 $n_files, $n_files / $d, 167 $n_files, $n_files / $d,
62 $n_stats, $n_stats / $d 168 $n_stats, $n_stats / $d;
63 if $opt_progress;
64 } 169 }
65 170
66 aioreq_pri -1; 171 aioreq_pri -1;
67 ++$n_dirs; 172 ++$n_dirs;
68 aio_scandir $path, 8, sub { 173 aio_scandir $path, 8, sub {
78 aio_wd $path, sub { 183 aio_wd $path, sub {
79 my $wd = shift; 184 my $wd = shift;
80 185
81 aio_lstat [$wd, $_] for @$files; 186 aio_lstat [$wd, $_] for @$files;
82 $n_stats += @$files; 187 $n_stats += @$files;
188 };
189 }
190
191 if ($opt_sync) {
192 aio_wd $path, sub {
193 my $wd = shift;
194
195 aio_pathsync [$wd, $_] for @$files;
196 aio_pathsync $wd;
83 }; 197 };
84 } 198 }
85 199
86 &scan ("$path$_") for @$dirs; 200 &scan ("$path$_") for @$dirs;
87 }; 201 };

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines