X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/431613ddf056b228a6eff5370d76e0753ca33da6..470722b48ea05e8267d95479f715193214359722:/x2p/find2perl.PL diff --git a/x2p/find2perl.PL b/x2p/find2perl.PL index da94dc9..e9275d0 100644 --- a/x2p/find2perl.PL +++ b/x2p/find2perl.PL @@ -29,7 +29,9 @@ print OUT <<"!GROK!THIS!"; $Config{startperl} eval 'exec $Config{perlpath} -S \$0 \${1+"\$@"}' if \$running_under_some_shell; -my \$perlpath = "$Config{perlpath}"; +(my \$perlpath = <<'/../') =~ s/\\s*\\z//; +$Config{perlpath} +/../ !GROK!THIS! # In the following, perl variables are not expanded during extraction. @@ -37,26 +39,20 @@ my \$perlpath = "$Config{perlpath}"; print OUT <<'!NO!SUBS!'; use strict; use vars qw/$statdone/; +use File::Spec::Functions 'curdir'; my $startperl = "#! $perlpath -w"; -# -# Modified September 26, 1993 to provide proper handling of years after 1999 -# Tom Link -# University of Pittsburgh -# -# Modified April 7, 1998 with nasty hacks to implement the troublesome -follow -# Billy Constantine -# University of Adelaide, Adelaide, South Australia -# -# Modified 1999-06-10, 1999-07-07 to migrate to cleaner perl5 usage -# Ken Pizzini +sub tab (); +sub n ($$); +sub fileglob_to_re ($); +sub quote ($); my @roots = (); while ($ARGV[0] =~ /^[^-!(]/) { push(@roots, shift); } -@roots = ('.') unless @roots; -for (@roots) { $_ = "e($_) } +@roots = (curdir()) unless @roots; +for (@roots) { $_ = quote($_) } my $roots = join(', ', @roots); my $find = "find"; @@ -67,33 +63,37 @@ my $flushall = ''; my $initfile = ''; my $initnewer = ''; my $out = ''; +my $declaresubs = "sub wanted;\n"; my %init = (); +my ($follow_in_effect,$Skip_And) = (0,0); +my $print_needed = 1; while (@ARGV) { $_ = shift; s/^-// || /^[()!]/ || die "Unrecognized switch: $_\n"; if ($_ eq '(') { - $out .= &tab . "(\n"; + $out .= tab . "(\n"; $indent_depth++; next; } elsif ($_ eq ')') { --$indent_depth; - $out .= &tab . ")"; + $out .= tab . ")"; } elsif ($_ eq 'follow') { + $follow_in_effect= 1; $stat = 'stat'; - $decl = "\nmy %already_seen = ();\n"; - $out .= &tab . '(not $already_seen{"$dev,$ino"}) &&' . "\n"; - $out .= &tab . '(($already_seen{"$dev,$ino"} = !(-d _)) || 1)'; + $Skip_And= 1; } elsif ($_ eq '!') { - $out .= &tab . "!"; + $out .= tab . "!"; next; - } elsif ($_ eq 'name') { - $out .= &tab . '/' . &fileglob_to_re(shift) . "/"; + } elsif (/^(i)?name$/) { + $out .= tab . '/' . fileglob_to_re(shift) . "/s$1"; + } elsif (/^(i)?path$/) { + $out .= tab . '$File::Find::name =~ /' . fileglob_to_re(shift) . "/s$1"; } elsif ($_ eq 'perm') { my $onum = shift; $onum =~ /^-?[0-7]+$/ || die "Malformed -perm argument: $onum\n"; - $out .= &tab; + $out .= tab; if ($onum =~ s/^-//) { $onum = sprintf("0%o", oct($onum) & 07777); $out .= "((\$mode & $onum) == $onum)"; @@ -103,14 +103,16 @@ while (@ARGV) { } } elsif ($_ eq 'type') { (my $filetest = shift) =~ tr/s/S/; - $out .= &tab . "-$filetest _"; + $out .= tab . "-$filetest _"; } elsif ($_ eq 'print') { - $out .= &tab . 'print("$name\n")'; + $out .= tab . 'print("$name\n")'; + $print_needed = 0; } elsif ($_ eq 'print0') { - $out .= &tab . 'print("$name\0")'; + $out .= tab . 'print("$name\0")'; + $print_needed = 0; } elsif ($_ eq 'fstype') { my $type = shift; - $out .= &tab; + $out .= tab; if ($type eq 'nfs') { $out .= '($dev < 0)'; } else { @@ -118,43 +120,43 @@ while (@ARGV) { } } elsif ($_ eq 'user') { my $uname = shift; - $out .= &tab . "(\$uid == \$uid{'$uname'})"; + $out .= tab . "(\$uid == \$uid{'$uname'})"; $init{user} = 1; } elsif ($_ eq 'group') { my $gname = shift; - $out .= &tab . "(\$gid == \$gid{'$gname'})"; + $out .= tab . "(\$gid == \$gid{'$gname'})"; $init{group} = 1; } elsif ($_ eq 'nouser') { - $out .= &tab . '!exists $uid{$uid}'; + $out .= tab . '!exists $uid{$uid}'; $init{user} = 1; } elsif ($_ eq 'nogroup') { - $out .= &tab . '!exists $gid{$gid}'; + $out .= tab . '!exists $gid{$gid}'; $init{group} = 1; } elsif ($_ eq 'links') { - $out .= &tab . &n('$nlink', shift); + $out .= tab . n('$nlink', shift); } elsif ($_ eq 'inum') { - $out .= &tab . &n('$ino', shift); + $out .= tab . n('$ino', shift); } elsif ($_ eq 'size') { $_ = shift; my $n = 'int(((-s _) + 511) / 512)'; - if (s/c$//) { + if (s/c\z//) { $n = 'int(-s _)'; - } elsif (s/k$//) { + } elsif (s/k\z//) { $n = 'int(((-s _) + 1023) / 1024)'; } - $out .= &tab . &n($n, $_); + $out .= tab . n($n, $_); } elsif ($_ eq 'atime') { - $out .= &tab . &n('int(-A _)', shift); + $out .= tab . n('int(-A _)', shift); } elsif ($_ eq 'mtime') { - $out .= &tab . &n('int(-M _)', shift); + $out .= tab . n('int(-M _)', shift); } elsif ($_ eq 'ctime') { - $out .= &tab . &n('int(-C _)', shift); + $out .= tab . n('int(-C _)', shift); } elsif ($_ eq 'exec') { my @cmd = (); while (@ARGV && $ARGV[0] ne ';') { push(@cmd, shift) } shift; - $out .= &tab; + $out .= tab; if ($cmd[0] =~m#^(?:(?:/usr)?/bin/)?rm$# && $cmd[$#cmd] eq '{}' && (@cmd == 2 || (@cmd == 3 && $cmd[1] eq '-f'))) { @@ -168,60 +170,69 @@ while (@ARGV) { } else { for (@cmd) { s/'/\\'/g } - { local $" = "','"; $out .= "&doexec(0, '@cmd')"; } + { local $" = "','"; $out .= "doexec(0, '@cmd')"; } + $declaresubs .= "sub doexec (\$\@);\n"; $init{doexec} = 1; } + $print_needed = 0; } elsif ($_ eq 'ok') { my @cmd = (); while (@ARGV && $ARGV[0] ne ';') { push(@cmd, shift) } shift; - $out .= &tab; + $out .= tab; for (@cmd) { s/'/\\'/g } - { local $" = "','"; $out .= "&doexec(0, '@cmd')"; } + { local $" = "','"; $out .= "doexec(1, '@cmd')"; } + $declaresubs .= "sub doexec (\$\@);\n"; $init{doexec} = 1; + $print_needed = 0; } elsif ($_ eq 'prune') { - $out .= &tab . '($File::Find::prune = 1)'; + $out .= tab . '($File::Find::prune = 1)'; } elsif ($_ eq 'xdev') { - $out .= &tab . '!($File::Find::prune |= ($dev != $File::Find::topdev))' + $out .= tab . '!($File::Find::prune |= ($dev != $File::Find::topdev))' ; } elsif ($_ eq 'newer') { my $file = shift; my $newername = 'AGE_OF' . $file; $newername =~ s/\W/_/g; $newername = '$' . $newername; - $out .= &tab . "(-M _ < $newername)"; - $initnewer .= "my $newername = -M " . "e($file) . ";\n"; + $out .= tab . "(-M _ < $newername)"; + $initnewer .= "my $newername = -M " . quote($file) . ";\n"; } elsif ($_ eq 'eval') { my $prog = shift; $prog =~ s/'/\\'/g; - $out .= &tab . "eval {$prog}"; + $out .= tab . "eval {$prog}"; + $print_needed = 0; } elsif ($_ eq 'depth') { $find = 'finddepth'; next; } elsif ($_ eq 'ls') { - $out .= &tab . "&ls"; + $out .= tab . "ls"; + $declaresubs .= "sub ls ();\n"; $init{ls} = 1; + $print_needed = 0; } elsif ($_ eq 'tar') { die "-tar must have a filename argument\n" unless @ARGV; my $file = shift; my $fh = 'FH' . $file; $fh =~ s/\W/_/g; - $out .= &tab . "&tar(*$fh, \$name)"; - $flushall .= "&tflushall;\n"; - $initfile .= "open($fh, " . "e('> ' . $file) . + $out .= tab . "tar(*$fh, \$name)"; + $flushall .= "tflushall;\n"; + $declaresubs .= "sub tar;\nsub tflushall ();\n"; + $initfile .= "open($fh, " . quote('> ' . $file) . qq{) || die "Can't open $fh: \$!\\n";\n}; $init{tar} = 1; - } elsif (/^(n?)cpio$/) { + } elsif (/^(n?)cpio\z/) { die "-$_ must have a filename argument\n" unless @ARGV; my $file = shift; my $fh = 'FH' . $file; $fh =~ s/\W/_/g; - $out .= &tab . "&cpio(*$fh, \$name, '$1')"; + $out .= tab . "cpio(*$fh, \$name, '$1')"; $find = 'finddepth'; - $flushall .= "&cflushall;\n"; - $initfile .= "open($fh, " . "e('> ' . $file) . + $flushall .= "cflushall;\n"; + $declaresubs .= "sub cpio;\nsub cflushall ();\n"; + $initfile .= "open($fh, " . quote('> ' . $file) . qq{) || die "Can't open $fh: \$!\\n";\n}; $init{cpio} = 1; } else { @@ -230,18 +241,24 @@ while (@ARGV) { if (@ARGV) { if ($ARGV[0] eq '-o') { - { local($statdone) = 1; $out .= "\n" . &tab . "||\n"; } + { local($statdone) = 1; $out .= "\n" . tab . "||\n"; } $statdone = 0 if $indent_depth == 1 && exists $init{delayedstat}; $init{saw_or} = 1; shift; } else { - $out .= " &&" unless $ARGV[0] eq ')'; + $out .= " &&" unless $Skip_And || $ARGV[0] eq ')'; $out .= "\n"; shift if $ARGV[0] eq '-a'; } } } +if ($print_needed) { + my $t = tab; + if ($t !~ /&&\s*$/) { $t .= '&& ' } + $out .= "\n" . $t . 'print("$name\n")'; +} + print <<"END"; $startperl @@ -260,8 +277,17 @@ use vars qw/*name *dir *prune/; *dir = *File::Find::dir; *prune = *File::Find::prune; +$declaresubs + END +if (exists $init{doexec}) { + print <<'END'; +use Cwd (); +my $cwd = Cwd::cwd(); + +END +} if (exists $init{ls}) { print <<'END'; @@ -301,10 +327,12 @@ if (exists $init{declarestat}) { END } +if ( $follow_in_effect ) { +$out =~ s/lstat\(\$_\)/lstat(_)/; print <<"END"; $decl # Traverse desired filesystems -File::Find::$find(\\&wanted, $roots); +File::Find::$find( {wanted => \\&wanted, follow => 1}, $roots); $flushall sub wanted { @@ -312,29 +340,37 @@ $out; } END +} else { +print <<"END"; +$decl +# Traverse desired filesystems +File::Find::$find({wanted => \\&wanted}, $roots); +$flushall + +sub wanted { +$out; +} +END +} if (exists $init{doexec}) { print <<'END'; -BEGIN { - require Cwd; - my $cwd = Cwd::cwd(); -} - -sub doexec { +sub doexec ($@) { my $ok = shift; - for my $word (@_) + my @command = @_; # copy so we don't try to s/// aliases to constants + for my $word (@command) { $word =~ s#{}#$name#g } if ($ok) { my $old = select(STDOUT); $| = 1; - print "@_"; + print "@command"; select($old); return 0 unless =~ /^y/; } chdir $cwd; #sigh - system @_; + system @command; chdir $File::Find::dir; return !$?; } @@ -350,7 +386,7 @@ sub sizemm { sprintf("%3d, %3d", ($rdev >> 8) & 0xff, $rdev & 0xff); } -sub ls { +sub ls () { my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, INTRO \$atime,\$mtime,\$ctime,\$blksize,\$blocks) = $stat(_); @@ -498,9 +534,9 @@ SUB } } -sub cflushall { +sub cflushall () { for my $fh (keys %cpout) { - &cpio($fh, undef, $nc{$fh}); + cpio($fh, undef, $nc{$fh}); $cpout{$fh} .= "0" x (5120 - length($cpout{$fh})); flush($fh, \$cpout{$fh}, 5120); print $blocks{$fh} * 10, " blocks\n"; @@ -602,7 +638,7 @@ SUB } } -sub tflushall { +sub tflushall () { my $len; for my $fh (keys %tarout) { $len = 10240 - length($tarout{$fh}); @@ -619,7 +655,7 @@ exit; ############################################################################ -sub tab { +sub tab () { my $tabstring; $tabstring = "\t" x ($indent_depth/2) . ' ' x ($indent_depth%2 * 4); @@ -642,22 +678,23 @@ sub tab { $tabstring; } -sub fileglob_to_re { +sub fileglob_to_re ($) { my $x = shift; - $x =~ s#([./^\$()])#\\$1#g; + $x =~ s#([./^\$()+])#\\$1#g; $x =~ s#([?*])#.$1#g; - "^$x\$"; + "^$x\\z"; } -sub n { +sub n ($$) { my ($pre, $n) = @_; $n =~ s/^-/< / || $n =~ s/^\+/> / || $n =~ s/^/== /; $n =~ s/ 0*(\d)/ $1/; "($pre $n)"; } -sub quote { +sub quote ($) { my $string = shift; + $string =~ s/\\/\\\\/g; $string =~ s/'/\\'/g; "'$string'"; } @@ -709,7 +746,12 @@ not evaluated if PREDICATE1 is true. =item C<-follow> -Follow (dereference) symlinks. [XXX doesn't work fully, see L] +Follow (dereference) symlinks. The checking of file attributes depends +on the position of the C<-follow> option. If it precedes the file +check option, an C is done which means the file check applies to the +file the symbolic link is pointing to. If C<-follow> option follows the +file check option, this now applies to the symbolic link itself, i.e. +an C is done. =item C<-depth> @@ -729,6 +771,18 @@ File name matches specified GLOB wildcard pattern. GLOB may need to be quoted to avoid interpretation by the shell (just as with using C). +=item C<-iname GLOB> + +Like C<-name>, but the match is case insensitive. + +=item C<-path GLOB> + +Path name matches specified GLOB wildcard pattern. + +=item C<-ipath GLOB> + +Like C<-path>, but the match is case insensitive. + =item C<-perm PERM> Low-order 9 bits of permission match octal value PERM. @@ -774,7 +828,7 @@ True if (hard) link count of file matches N (see below). True if file's size matches N (see below) N is normally counted in 512-byte blocks, but a suffix of "c" specifies that size should be -counted in characters (bytes) and a suffix of "k" specifes that +counted in characters (bytes) and a suffix of "k" specifies that size should be counted in 1024-byte blocks. =item C<-atime N> @@ -797,7 +851,9 @@ True if last-modified time of file matches N. =item C<-print> -Print out path of file (always true). +Print out path of file (always true). If none of C<-exec>, C<-ls>, +C<-print0>, or C<-ok> is specified, then C<-print> will be added +implicitly. =item C<-print0> @@ -805,7 +861,7 @@ Like -print, but terminates with \0 instead of \n. =item C<-exec OPTIONS ;> -exec() the arguments in OPTIONS in a subprocess; any occurence of {} in +exec() the arguments in OPTIONS in a subprocess; any occurrence of {} in OPTIONS will first be substituted with the path of the current file. Note that the command "rm" has been special-cased to use perl's unlink() function instead (as an optimization). The C<;> must be passed as @@ -821,12 +877,9 @@ a distinct argument, so it may need to be surrounded by whitespace and/or quoted from interpretation by the shell using a backslash (just as with using C). -=item C<-eval EXPR ;> +=item C<-eval EXPR> -Has the perl script eval() the EXPR. The C<;> must be passed as -a distinct argument, so it may need to be surrounded by whitespace and/or -quoted from interpretation by the shell using a backslash (just as with -using C). +Has the perl script eval() the EXPR. =item C<-ls> @@ -852,14 +905,9 @@ Predicates which take a numeric argument N can come in three forms: * N is prefixed with a -: match values less than N * N is not prefixed with either + or -: match only values equal to N -=head1 BUGS - -The -follow option doesn't really work yet, because File::Find doesn't -support following symlinks. - =head1 SEE ALSO -find +find, File::Find. =cut !NO!SUBS!