9 B<vidir> [--verbose] [directory|file|-] ...
13 vidir allows editing of the contents of a directory in a text editor. If no
14 directory is specified, the current directory is edited.
16 When editing a directory, each item in the directory will appear on its own
17 numbered line. These numbers are how vidir keeps track of what items are
18 changed. Delete lines to remove files from the directory, or
19 edit filenames to rename files. You can also switch pairs of numbers to
22 Note that if "-" is specified as the directory to edit, it reads a list of
23 filenames from stdin and displays those for editing. Alternatively, a list
24 of files can be specified on the command line.
32 Verbosely display the actions taken by the program.
48 Edit subdirectory contents too. To delete subdirectories,
49 delete all their contents and the subdirectory itself in the editor.
51 =item find -type f | vidir -
53 Edit all files under the current directory and subdirectories.
57 =head1 ENVIRONMENT VARIABLES
67 Also supported to determine what editor to use.
73 Copyright 2006 by Joey Hess <id@joeyh.name>
75 Licensed under the GNU GPL.
80 use File
::Path
qw(make_path);
88 if (! GetOptions
("verbose|v" => \
$verbose)) {
89 die "Usage: $0 [--verbose] [directory|file|-]\n";
96 foreach my $item (@ARGV) {
98 push @dir, map { chomp; $_ } <STDIN
>;
100 open(STDIN
, "/dev/tty") || die "reopen: $!\n";
104 opendir(DIR
, $item) || die "$0: cannot read $item: $!\n";
105 push @dir, map { "$item$_" } sort readdir(DIR
);
113 if (grep(/[[:cntrl:]]/, @dir)) {
114 die "$0: control characters in filenames are not supported\n";
117 my $tmp=File
::Temp
->new(TEMPLATE
=> "dirXXXXX", DIR
=> File
::Spec
->tmpdir);
118 open (OUT
, ">".$tmp->filename) || die "$0: cannot create ".$tmp->filename.": $!\n";
123 next if /^(.*\/)?\
.$/ || /^(.*\
/)?\.\.$/;
125 print OUT
"$c\t$_\n";
128 close OUT
|| die "$0: cannot write ".$tmp->filename.": $!\n";
131 if (-x
"/usr/bin/editor") {
132 @editor="/usr/bin/editor";
134 if (exists $ENV{EDITOR
}) {
135 @editor=split(' ', $ENV{EDITOR
});
137 if (exists $ENV{VISUAL
}) {
138 @editor=split(' ', $ENV{VISUAL
});
140 $ret=system(@editor, $tmp);
142 die "@editor exited nonzero, aborting\n";
145 open (IN
, $tmp->filename) || die "$0: cannot read ".$tmp->filename.": $!\n";
148 if (/^(\d+)\t{0,1}(.*)/) {
151 if (! exists $item{$num}) {
152 die "$0: unknown item number $num\n";
154 elsif ($name ne $item{$num}) {
155 next unless length $name;
157 my $dir=dirname
($name);
159 if (! (-e
$src || -l
$src) ) {
160 print STDERR
"$0: $src does not exist\n";
166 if (-e
$name || -l
$name) {
169 while (-e
$tmp || -l
$tmp) {
173 if (! rename($name, $tmp)) {
174 print STDERR
"$0: failed to rename $name to $tmp: $!\n";
178 print "'$name' -> '$tmp'\n";
180 foreach my $item (keys %item) {
181 if ($item{$item} eq $name) {
187 if ((! -d
$dir) && (! make_path
($dir, {
190 print STDERR
"$0: failed to create directory tree $dir: $!\n";
193 elsif (! rename($src, $name)) {
194 print STDERR
"$0: failed to rename $src to $name: $!\n";
199 foreach (values %item) {
200 s
,^\Q
$src\E
($|/),$name$1,;
204 print "'$src' => '$name'\n";
214 die "$0: unable to parse line \"$_\", aborting\n";
217 close IN
|| die "$0: cannot read ".$tmp->filename.": $!\n";
218 unlink($tmp.'~') if -e
$tmp.'~';
223 if (-d
$file && ! -l
$file) {
231 foreach my $item (reverse sort values %item) {
233 print STDERR
"$0: failed to remove $item: $!\n";
237 print "removed '$item'\n";