Package: moreutils

----- Forwarded message from Moshe Kamensky <[EMAIL PROTECTED]> -----

From: Moshe Kamensky <[EMAIL PROTECTED]>
Date: Mon, 1 Jan 2007 13:59:34 +0000
To: Joey Hess <[EMAIL PROTECTED]>
Subject: vidir modifications
User-Agent: Mutt/1.5.11

Hi,

I've been using your vidir script (part of moreutils), and found it very 
useful. I made two modifications, in the attached patch:

1. Added a --long option, which lists the files with permissions and 
   owner, and allows to change them.

2. Added a --pretend option, which outputs shell commands performing the 
   required modifications, instead of actually making them.

Thanks,
Moshe


--- vidir.orig  2006-11-12 03:01:36.000000000 +0000
+++ vidir       2007-01-01 13:35:25.039264000 +0000
@@ -6,7 +6,7 @@
 
 =head1 SYNOPSIS
 
-B<vidir> [--verbose] [directory|file|-] ...
+B<vidir> [--verbose] [--pretend] [--long] [directory|file|-] ...
 
 =head1 DESCRIPTION
 
@@ -31,6 +31,17 @@
 
 Verbosely display the actions taken by the program.
 
+=item -p, --pretend
+
+Instead of actually performing the operations, produces a list of shell
+commands to achieve the same effect. Probably doesn't make sense together
+with B<--verbose>.
+
+=item -l, --long
+
+In addition to file names, produces for each file the (octal) mode, user and
+group. These can be modified as well.
+
 =back
 
 =head1 ENVIRONMENT VARIABLES
@@ -62,14 +73,84 @@
 
 use File::Temp;
 use Getopt::Long;
+use warnings;
+use strict;
 
 my $error=0;
 
 my $verbose=0;
-if (! GetOptions("verbose|v" => \$verbose)) {
+my $long = 0;
+my $pretend = 0;
+unless ( GetOptions(
+       'verbose|v' => \$verbose, 
+       'pretend|p!' => \$pretend, 
+       'long|l!' => \$long,
+) ) {
        die "Usage: $0 [--verbose] [directory|file|-]\n";
 }
 
+use vars qw($rename $unlink $chmod $chown $file_exists %rev);
+
+if ( $pretend ) {
+       $rename = sub { print "mv $_[0] $_[1]\n"; delete $rev{$_[0]}; 1 };
+       $unlink = sub { print "rm @_\n"; delete $rev{$_[0]}; 1 };
+       $chmod = sub { printf("chmod %04o %s\n", @_); 1 };
+       $chown = sub { 
+               printf("chown %s:%s %s\n", uid2str($_[0]), gid2str($_[1]), 
$_[2]);
+               1
+       };
+       $file_exists = sub { exists $rev{shift()} };
+} else {
+       $rename = sub { rename $_[0], $_[1] };
+       $unlink = sub { unlink @_ };
+       $chmod = sub { chmod @_ };
+       $chown = sub { chown @_ };
+       $file_exists = sub { -l shift || -e _ };
+}
+
+sub mode2str {
+       sprintf("%04o", shift);
+}
+
+sub str2mode {
+       oct(shift);
+}
+
+sub uid2str {
+       my $uid = shift;
+       my $suid = getpwuid($uid);
+       $suid ? $suid : $uid;
+}
+
+sub str2uid {
+       my $suid = shift;
+       my $uid = getpwnam($suid);
+       defined($uid) ? $uid : $suid;
+}
+
+sub gid2str {
+       my $gid = shift;
+       my $sgid = getgrgid($gid);
+       $sgid ? $sgid : $gid;
+}
+
+sub str2gid {
+       my $sgid = shift;
+       my $gid = getgrnam($sgid);
+       defined($gid) ? $gid : $sgid;
+}
+
+use vars qw(@mode @uid @gid);
+
+sub long {
+       use Fcntl ':mode';
+       my ($file, $c) = @_;
+       ($mode[$c], $uid[$c], $gid[$c]) = (stat $file)[2,4,5];
+       $mode[$c] = S_IMODE($mode[$c]);
+       join(' ', mode2str($mode[$c]), uid2str($uid[$c]), 
+                 gid2str($gid[$c]), $file)
+}
+
 my @dir;
 if (! @ARGV) {
        push @ARGV, "."
@@ -89,7 +170,7 @@
                push @dir, $item;
        }
 }
-       
+
 my $tmp=File::Temp->new(template => "dirXXXXX");
 open (OUT, ">".$tmp->filename) || die "$0: cannot write ".$tmp->filename.": 
$!\n";
 
@@ -98,7 +179,9 @@
 foreach (@dir) {
        next if /^(.*\/)?\.$/ || /^(.*\/)?\.\.$/;
        $item{++$c}=$_;
-       print OUT "$c\t$_\n";
+       $rev{$_}=$c;
+       my $file = $long ? long($_, $c) : $_;
+       print OUT "$c\t$file\n";
 }
 @dir=();
 close OUT;
@@ -113,7 +196,7 @@
 if (exists $ENV{VISUAL}) {
        @editor=split(' ', $ENV{VISUAL});
 }
-$ret=system(@editor, $tmp);
+my $ret=system(@editor, $tmp);
 if ($ret != 0) {
        die "@editor exited nonzero, aborting\n";
 }
@@ -121,40 +204,65 @@
 open (IN, $tmp->filename) || die "$0: cannot read ".$tmp->filename.": $!\n";
 while (<IN>) {
        chomp;
+       next if /^\s*$/ or /^\s*#/;
        if (/^(\d+)\t{0,1}(.*)/) {
                my $num=$1;
                my $name=$2;
-               if (! exists $item{$num}) {
+               my $src = $item{$num};
+               unless (defined $src) {
                        print STDERR "$0: unknown item number $num\n";
                        $error=1;
+                       next;
                }
-               elsif ($name ne $item{$num}) {
+               if ( $long ) {
+                       (my ($mode, $uid, $gid), $name) = split(' ', $name, 4);
+
+                       $mode = str2mode($mode);
+                       if ( $mode != $mode[$num] ) {
+                               if (!&$chmod($mode, $src)) {
+                                       print STDERR "$0: failed to chmod $src 
to $mode: $!\n";
+                                       $error=1;
+                               } elsif ($verbose) {
+                                       printf("'$src': %s -> %s\n", 
mode2str($mode[$num]), mode2str($mode));
+                               }
+                       }
+
+                       $uid = str2uid($uid);
+                       $gid = str2gid($gid);
+                       if ( $uid != $uid[$num] or $gid != $gid[$num] ) {
+                               if (!&$chown($uid, $gid, $src)) {
+                                       print STDERR "$0: failed to chown $src 
to '$uid:$gid': $!\n";
+                                       $error=1;
+                               } elsif ($verbose) {
+                                       print "'$src': $uid[$num]:$gid[$num] -> 
$uid:$gid\n";
+                               }
+                       }
+               }
+
+               if ($name ne $item{$num}) {
                        next unless length $name;
-                       my $src=$item{$num};
-                       
+
                        # deal with swaps
-                       if (-e $name || -l $name) {
+                       if (&$file_exists($name)) {
                                my $tmp=$name."~";
                                my $c=0;
-                               while (-e $tmp || -l $tmp) {
+                               while (&$file_exists($tmp)) {
                                        $c++;
                                        $tmp=$name."~$c";
                                }
-                               if (! rename($name, $tmp)) {
+                               $rev{$tmp} = delete $rev{$name};
+                               $item{$rev{$tmp}}=$tmp;
+                               if (! &$rename($name, $tmp)) {
                                        print STDERR "$0: failed to rename 
$name to $tmp: $!\n";
                                        $error=1;
                                }
                                elsif ($verbose) {
                                        print "'$name' -> '$tmp'\n";
                                }
-                               foreach my $item (keys %item) {
-                                       if ($item{$item} eq $name) {
-                                               $item{$item}=$tmp;
-                                       }
-                               }
+
                        }
 
-                       if (! rename($src, $name)) {
+                       if (! &$rename($src, $name)) {
                                print STDERR "$0: failed to rename $src to 
$name: $!\n";
                                $error=1;
                        }
@@ -164,9 +272,6 @@
                }
                delete $item{$num};
        }
-       elsif (/^\s*$/) {
-               # skip empty line
-       }
        else {
                die "$0: unable to parse line \"$_\", aborting\n";
        }
@@ -175,7 +280,7 @@
 unlink($tmp.'~') if -e $tmp.'~';
 
 foreach my $item (sort values %item) {
-       if (! unlink($item)) {
+       if (! &$unlink($item)) {
                print STDERR "$0: failed to remove $item: $!\n";
                $error=1;
        }
@@ -185,3 +290,5 @@
 }
 
 exit $error;
+
+# vim: sw=8 noet:




----- End forwarded message -----

-- 
see shy jo

Attachment: signature.asc
Description: Digital signature

Reply via email to