2 eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
3 if $running_under_some_shell;
4 (my $perlpath = <<'/../') =~ s/\s*\z//;
8 use vars qw
/$statdone/;
9 use File
::Spec
::Functions
'curdir';
10 my $startperl = "#! $perlpath -w";
13 # Modified September 26, 1993 to provide proper handling of years after 1999
14 # Tom Link <tml+@pitt.edu>
15 # University of Pittsburgh
17 # Modified April 7, 1998 with nasty hacks to implement the troublesome -follow
18 # Billy Constantine <wdconsta@cs.adelaide.edu.au> <billy@smug.adelaide.edu.au>
19 # University of Adelaide, Adelaide, South Australia
21 # Modified 1999-06-10, 1999-07-07 to migrate to cleaner perl5 usage
22 # Ken Pizzini <ken@halcyon.com>
24 # Modified 2000-01-28 to use the 'follow' option of File::Find
27 while ($ARGV[0] =~ /^[^-!(]/) {
30 @roots = (curdir
()) unless @roots;
31 for (@roots) { $_ = "e
($_) }
32 my $roots = join(', ', @roots);
43 my ($follow_in_effect,$Skip_And) = (0,0);
47 s/^-// || /^[()!]/ || die "Unrecognized switch: $_\n";
55 } elsif ($_ eq 'follow') {
62 } elsif ($_ eq 'name') {
63 $out .= &tab
. '/' . &fileglob_to_re
(shift) . "/s";
64 } elsif ($_ eq 'perm') {
67 || die "Malformed -perm argument: $onum\n";
69 if ($onum =~ s/^-//) {
70 $onum = sprintf("0%o", oct($onum) & 07777);
71 $out .= "((\$mode & $onum) == $onum)";
74 $out .= "((\$mode & 0777) == $onum)";
76 } elsif ($_ eq 'type') {
77 (my $filetest = shift) =~ tr/s/S/;
78 $out .= &tab
. "-$filetest _";
79 } elsif ($_ eq 'print') {
80 $out .= &tab
. 'print("$name\n")';
81 } elsif ($_ eq 'print0') {
82 $out .= &tab
. 'print("$name\0")';
83 } elsif ($_ eq 'fstype') {
89 $out .= '($dev >= 0)'; #XXX
91 } elsif ($_ eq 'user') {
93 $out .= &tab
. "(\$uid == \$uid{'$uname'})";
95 } elsif ($_ eq 'group') {
97 $out .= &tab
. "(\$gid == \$gid{'$gname'})";
99 } elsif ($_ eq 'nouser') {
100 $out .= &tab
. '!exists $uid{$uid}';
102 } elsif ($_ eq 'nogroup') {
103 $out .= &tab
. '!exists $gid{$gid}';
105 } elsif ($_ eq 'links') {
106 $out .= &tab
. &n
('$nlink', shift);
107 } elsif ($_ eq 'inum') {
108 $out .= &tab
. &n
('$ino', shift);
109 } elsif ($_ eq 'size') {
111 my $n = 'int(((-s _) + 511) / 512)';
115 $n = 'int(((-s _) + 1023) / 1024)';
117 $out .= &tab
. &n
($n, $_);
118 } elsif ($_ eq 'atime') {
119 $out .= &tab
. &n
('int(-A _)', shift);
120 } elsif ($_ eq 'mtime') {
121 $out .= &tab
. &n
('int(-M _)', shift);
122 } elsif ($_ eq 'ctime') {
123 $out .= &tab
. &n
('int(-C _)', shift);
124 } elsif ($_ eq 'exec') {
126 while (@ARGV && $ARGV[0] ne ';')
127 { push(@cmd, shift) }
130 if ($cmd[0] =~m
#^(?:(?:/usr)?/bin/)?rm$#
131 && $cmd[$#cmd] eq '{}'
132 && (@cmd == 2 || (@cmd == 3 && $cmd[1] eq '-f'))) {
134 $out .= '(unlink($_) || warn "$name: $!\n")';
136 $out .= 'unlink($_)';
138 $out .= '(unlink($_) || 1)';
143 { local $" = "','"; $out .= "&doexec
(0, '@cmd')"; }
146 } elsif ($_ eq 'ok') {
148 while (@ARGV && $ARGV[0] ne ';')
149 { push(@cmd, shift) }
154 { local $" = "','"; $out .= "&doexec(0, '@cmd')"; }
156 } elsif ($_ eq 'prune') {
157 $out .= &tab
. '($File::Find::prune = 1)';
158 } elsif ($_ eq 'xdev') {
159 $out .= &tab
. '!($File::Find::prune |= ($dev != $File::Find::topdev))'
161 } elsif ($_ eq 'newer') {
163 my $newername = 'AGE_OF' . $file;
164 $newername =~ s/\W/_/g;
165 $newername = '$' . $newername;
166 $out .= &tab
. "(-M _ < $newername)";
167 $initnewer .= "my $newername = -M " . "e
($file) . ";\n";
168 } elsif ($_ eq 'eval') {
171 $out .= &tab
. "eval {$prog}";
172 } elsif ($_ eq 'depth') {
175 } elsif ($_ eq 'ls') {
176 $out .= &tab
. "&ls";
178 } elsif ($_ eq 'tar') {
179 die "-tar must have a filename argument\n" unless @ARGV;
181 my $fh = 'FH' . $file;
183 $out .= &tab
. "&tar(*$fh, \$name)";
184 $flushall .= "&tflushall;\n";
185 $initfile .= "open($fh, " . "e
('> ' . $file) .
186 qq{) || die "Can't open $fh: \$!\\n";\n};
188 } elsif (/^(n?)cpio\z/) {
189 die "-$_ must have a filename argument\n" unless @ARGV;
191 my $fh = 'FH' . $file;
193 $out .= &tab
. "&cpio(*$fh, \$name, '$1')";
195 $flushall .= "&cflushall;\n";
196 $initfile .= "open($fh, " . "e
('> ' . $file) .
197 qq{) || die "Can't open $fh: \$!\\n";\n};
200 die "Unrecognized switch: -$_\n";
204 if ($ARGV[0] eq '-o') {
205 { local($statdone) = 1; $out .= "\n" . &tab
. "||\n"; }
206 $statdone = 0 if $indent_depth == 1 && exists $init{delayedstat
};
210 $out .= " &&" unless $Skip_And || $ARGV[0] eq ')';
212 shift if $ARGV[0] eq '-a';
220 eval 'exec $perlpath -S \$0 \${1+"\$@"}'
221 if 0; #\$running_under_some_shell
226 # Set the variable \$File::Find::dont_use_nlink if you're using AFS,
229 # for the convenience of &wanted calls, including -eval statements:
230 use vars qw/*name *dir *prune/;
231 *name = *File::Find::name;
232 *dir = *File::Find::dir;
233 *prune = *File::Find::prune;
238 if (exists $init{ls
}) {
240 my @rwx = qw(--- --x -w- -wx r-- r-x rw- rwx);
241 my @moname = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
246 if (exists $init{user
} || exists $init{ls
} || exists $init{tar
}) {
247 print "my (%uid, %user);\n";
248 print "while (my (\$name, \$pw, \$uid) = getpwent) {\n";
249 print ' $uid{$name} = $uid{$uid} = $uid;', "\n"
250 if exists $init{user
};
251 print ' $user{$uid} = $name unless exists $user{$uid};', "\n"
252 if exists $init{ls
} || exists $init{tar
};
256 if (exists $init{group
} || exists $init{ls
} || exists $init{tar
}) {
257 print "my (%gid, %group);\n";
258 print "while (my (\$name, \$pw, \$gid) = getgrent) {\n";
259 print ' $gid{$name} = $gid{$gid} = $gid;', "\n"
260 if exists $init{group
};
261 print ' $group{$gid} = $name unless exists $group{$gid};', "\n"
262 if exists $init{ls
} || exists $init{tar
};
266 print $initnewer, "\n" if $initnewer ne '';
267 print $initfile, "\n" if $initfile ne '';
268 $flushall .= "exit;\n";
269 if (exists $init{declarestat
}) {
270 $out = <<'END' . $out;
271 my ($dev,$ino,$mode,$nlink,$uid,$gid);
276 if ( $follow_in_effect ) {
277 $out =~ s/lstat\(\$_\)/lstat(_)/;
280 # Traverse desired filesystems
281 File::Find::$find( {wanted => \\&wanted, follow => 1}, $roots);
292 # Traverse desired filesystems
293 File::Find::$find({wanted => \\&wanted}, $roots);
303 if (exists $init{doexec
}) {
307 my $cwd = Cwd::cwd();
312 { $word =~ s#{}#$name#g }
314 my $old = select(STDOUT);
318 return 0 unless <STDIN> =~ /^y/;
322 chdir $File::Find::dir;
329 if (exists $init{ls
}) {
330 print <<'INTRO', <<"SUB", <<'END';
334 sprintf("%3d, %3d", ($rdev >> 8) & 0xff, $rdev & 0xff);
338 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
340 \$atime,\$mtime,\$ctime,\$blksize,\$blocks) = $stat(_);
345 or $blocks = int(($size + 1023) / 1024);
347 my $perms = $rwx[$mode & 7];
349 $perms = $rwx[$mode & 7] . $perms;
351 $perms = $rwx[$mode & 7] . $perms;
352 substr($perms, 2, 1) =~ tr/-x/Ss/ if -u _;
353 substr($perms, 5, 1) =~ tr/-x/Ss/ if -g _;
354 substr($perms, 8, 1) =~ tr/-x/Tt/ if -k _;
355 if (-f _) { $perms = '-' . $perms; }
356 elsif (-d _) { $perms = 'd' . $perms; }
357 elsif (-l _) { $perms = 'l' . $perms; $pname .= ' -> ' . readlink($_); }
358 elsif (-c _) { $perms = 'c' . $perms; $size = sizemm($rdev); }
359 elsif (-b _) { $perms = 'b' . $perms; $size = sizemm($rdev); }
360 elsif (-p _) { $perms = 'p' . $perms; }
361 elsif (-S _) { $perms = 's' . $perms; }
362 else { $perms = '?' . $perms; }
364 my $user = $user{$uid} || $uid;
365 my $group = $group{$gid} || $gid;
367 my ($sec,$min,$hour,$mday,$mon,$timeyear) = localtime($mtime);
368 if (-M _ > 365.25 / 2) {
371 $timeyear = sprintf("%02d:%02d", $hour, $min);
374 printf "%5lu %4ld %-10s %3d %-8s %-8s %8s %s %2d %5s %s\n",
393 if (exists $init{cpio
} || exists $init{tar
}) {
399 my ($fh, $varref, $blksz) = @_;
401 while (length($$varref) >= $blksz) {
403 syswrite($fh, $$varref, $blksz);
404 substr($$varref, 0, $blksz) = '';
413 if (exists $init{cpio
}) {
414 print <<'INTRO', <<"SUB", <<'END';
420 my ($fh, $fname, $nc) = @_;
422 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
423 $atime,$mtime,$ctime,$blksize,$blocks);
426 if ( ! defined $fname ) {
427 $fname = 'TRAILER!!!';
428 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
429 $atime,$mtime,$ctime,$blksize,$blocks) = (0) x 13;
431 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
433 \$atime,\$mtime,\$ctime,\$blksize,\$blocks) = $stat(_);
436 open(IN, "./$_\0") || do {
437 warn "Couldn't open $fname: $!\n";
441 $text = readlink($_);
442 $size = 0 unless defined $text;
450 sprintf("%06o%06o%06o%06o%06o%06o%06o%06o%011lo%06o%011lo%s\0",
464 $cpout{$fh} .= "\0" if length($cpout{$fh}) & 1;
465 $cpout{$fh} .= pack("SSSSSSSSLSLa*",
466 070707, $dev, $ino, $mode, $uid, $gid, $nlink, $rdev, $mtime,
467 length($fname)+1, $size,
468 $fname . (length($fname) & 1 ? "\0" : "\0\0"));
472 $cpout{$fh} .= $text;
475 flush($fh, \$cpout{$fh}, 5120)
476 while ($l = length($cpout{$fh})) >= 5120;
477 while (sysread(IN, $cpout{$fh}, 5120 - $l, $l)) {
478 flush($fh, \$cpout{$fh}, 5120);
479 $l = length($cpout{$fh});
486 for my $fh (keys %cpout) {
487 &cpio($fh, undef, $nc{$fh});
488 $cpout{$fh} .= "0" x (5120 - length($cpout{$fh}));
489 flush($fh, \$cpout{$fh}, 5120);
490 print $blocks{$fh} * 10, " blocks\n";
497 if (exists $init{tar
}) {
498 print <<'INTRO', <<"SUB", <<'END';
504 my ($fh, $fname) = @_;
508 my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
510 \$atime,\$mtime,\$ctime,\$blksize,\$blocks) = $stat(_);
515 if ($linkname = $linkseen{$fh, $dev, $ino}) {
516 if (length($linkname) > 100) {
517 warn "$0: omitting file with linkname ",
518 "too long for tar output: $linkname\n";
524 $linkseen{$fh, $dev, $ino} = $fname;
527 if ($typeflag eq '0') {
529 open(IN, "./$_\0") || do {
530 warn "Couldn't open $fname: $!\n";
534 $linkname = readlink($_);
535 if (defined $linkname) { $typeflag = '2' }
536 elsif (-c _) { $typeflag = '3' }
537 elsif (-b _) { $typeflag = '4' }
538 elsif (-d _) { $typeflag = '5' }
539 elsif (-p _) { $typeflag = '6' }
543 if (length($fname) > 100) {
544 ($prefix, $fname) = ($fname =~ m#\A(.*?)/(.{,100})\Z(?!\n)#);
545 if (!defined($fname) || length($prefix) > 155) {
546 warn "$0: omitting file with name too long for tar output: ",
552 $size = 0 if $typeflag ne '0';
553 my $header = pack("a100a8a8a8a12a12a8a1a100a6a2a32a32a8a8a155",
555 sprintf("%7o ", $mode & 0777),
556 sprintf("%7o ", $uid & 0777777),
557 sprintf("%7o ", $gid & 0777777),
558 sprintf("%11o ", $size),
559 sprintf("%11o ", $mtime),
562 defined $linkname ? $linkname : '',
571 substr($header, 148, 8) = sprintf("%7o ", unpack("%16C*", $header));
572 my $l = length($header) % 512;
573 $tarout{$fh} .= $header;
574 $tarout{$fh} .= "\0" x (512 - $l) if $l;
577 flush($fh, \$tarout{$fh}, 10240)
578 while ($l = length($tarout{$fh})) >= 10240;
579 while (sysread(IN, $tarout{$fh}, 10240 - $l, $l)) {
580 my $slop = length($tarout{$fh}) % 512;
581 $tarout{$fh} .= "\0" x (512 - $slop) if $slop;
582 flush($fh, \$tarout{$fh}, 10240);
583 $l = length($tarout{$fh});
591 for my $fh (keys %tarout) {
592 $len = 10240 - length($tarout{$fh});
593 $len += 10240 if $len < 1024;
594 $tarout{$fh} .= "\0" x $len;
595 flush($fh, \$tarout{$fh}, 10240);
604 ############################################################################
609 $tabstring = "\t" x
($indent_depth/2) . ' ' x
($indent_depth%2 * 4);
611 if ($_ =~ /^(?:name|print|prune|exec|ok|\(|\))/) {
612 $init{delayedstat
} = 1;
614 my $statcall = '(($dev,$ino,$mode,$nlink,$uid,$gid) = '
616 if (exists $init{saw_or
}) {
617 $tabstring .= "(\$nlink || $statcall) &&\n" . $tabstring;
619 $tabstring .= "$statcall &&\n" . $tabstring;
622 $init{declarestat
} = 1;
625 $tabstring =~ s/^\s+/ / if $out =~ /!$/;
631 $x =~ s
#([./^\$()])#\\$1#g;
632 $x =~ s
#([?*])#.$1#g;
638 $n =~ s/^-/< / || $n =~ s/^\+/> / || $n =~ s/^/== /;
639 $n =~ s/ 0*(\d)/ $1/;
645 $string =~ s/\\/\\\\/g;
646 $string =~ s/'/\\'/g;
654 find2perl - translate find command lines to Perl code
658 find2perl [paths] [predicates] | perl
662 find2perl is a little translator to convert find command lines to
663 equivalent Perl code. The resulting code is typically faster than
666 "paths" are a set of paths where find2perl will start its searches and
667 "predicates" are taken from the following list.
673 Negate the sense of the following predicate. The C<!> must be passed as
674 a distinct argument, so it may need to be surrounded by whitespace and/or
675 quoted from interpretation by the shell using a backslash (just as with
678 =item C<( PREDICATES )>
680 Group the given PREDICATES. The parentheses must be passed as distinct
681 arguments, so they may need to be surrounded by whitespace and/or
682 quoted from interpretation by the shell using a backslash (just as with
685 =item C<PREDICATE1 PREDICATE2>
687 True if _both_ PREDICATE1 and PREDICATE2 are true; PREDICATE2 is not
688 evaluated if PREDICATE1 is false.
690 =item C<PREDICATE1 -o PREDICATE2>
692 True if either one of PREDICATE1 or PREDICATE2 is true; PREDICATE2 is
693 not evaluated if PREDICATE1 is true.
697 Follow (dereference) symlinks. The checking of file attributes depends
698 on the position of the C<-follow> option. If it precedes the file
699 check option, an C<stat> is done which means the file check applies to the
700 file the symbolic link is pointing to. If C<-follow> option follows the
701 file check option, this now applies to the symbolic link itself, i.e.
706 Change directory traversal algorithm from breadth-first to depth-first.
710 Do not descend into the directory currently matched.
714 Do not traverse mount points (prunes search at mount-point directories).
718 File name matches specified GLOB wildcard pattern. GLOB may need to be
719 quoted to avoid interpretation by the shell (just as with using
724 Low-order 9 bits of permission match octal value PERM.
728 The bits specified in PERM are all set in file's permissions.
732 The file's type matches perl's C<-X> operator.
734 =item C<-fstype TYPE>
736 Filesystem of current path is of type TYPE (only NFS/non-NFS distinction
741 True if USER is owner of file.
743 =item C<-group GROUP>
745 True if file's group is GROUP.
749 True if file's owner is not in password database.
753 True if file's group is not in group database.
757 True file's inode number is INUM.
761 True if (hard) link count of file matches N (see below).
765 True if file's size matches N (see below) N is normally counted in
766 512-byte blocks, but a suffix of "c" specifies that size should be
767 counted in characters (bytes) and a suffix of "k" specifes that
768 size should be counted in 1024-byte blocks.
772 True if last-access time of file matches N (measured in days) (see
777 True if last-changed time of file's inode matches N (measured in days,
782 True if last-modified time of file matches N (measured in days, see below).
786 True if last-modified time of file matches N.
790 Print out path of file (always true).
794 Like -print, but terminates with \0 instead of \n.
796 =item C<-exec OPTIONS ;>
798 exec() the arguments in OPTIONS in a subprocess; any occurence of {} in
799 OPTIONS will first be substituted with the path of the current
800 file. Note that the command "rm" has been special-cased to use perl's
801 unlink() function instead (as an optimization). The C<;> must be passed as
802 a distinct argument, so it may need to be surrounded by whitespace and/or
803 quoted from interpretation by the shell using a backslash (just as with
806 =item C<-ok OPTIONS ;>
808 Like -exec, but first prompts user; if user's response does not begin
809 with a y, skip the exec. The C<;> must be passed as
810 a distinct argument, so it may need to be surrounded by whitespace and/or
811 quoted from interpretation by the shell using a backslash (just as with
816 Has the perl script eval() the EXPR.
820 Simulates C<-exec ls -dils {} ;>
824 Adds current output to tar-format FILE.
828 Adds current output to old-style cpio-format FILE.
832 Adds current output to "new"-style cpio-format FILE.
836 Predicates which take a numeric argument N can come in three forms:
838 * N is prefixed with a +: match values greater than N
839 * N is prefixed with a -: match values less than N
840 * N is not prefixed with either + or -: match only values equal to N