home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


A.12 Chapter 13, File and Directory Manipulation

  1. Here's one way to do it:

    
    
    unlink @ARGV;

    Yup, that's it. The @ARGV array is a list of names to be removed. The unlink operator takes a list of names, so we just marry the two, and we're done.

    Of course, this doesn't handle error reporting, or the -f or -i options, or anything like that, but that'd just be gravy. If you did that, good!

  2. Here's one way to do it:

    ($old, $new) = @ARGV; # name them
    if (-d $new) { # new name is a directory, need to patch it up
        ($basename = $old) =~ 
    
    
    
    s#.*/##s; # get basename of $old
        $new .= "/$basename"; # and append it to new name
    }
    
    
    rename($old,$new) || die "Cannot rename $old to $new: $!";

    The workhorse in this program is the last line, but the remainder of the program is necessary for the case where the name we are renaming to is a directory.

    First, we give understandable names to the two elements of @ARGV . Then, if the $new name is a directory, we need to patch it by adding the basename of the $old name to the end of the new name. This means that renaming /usr/src/fred to /etc results in really renaming /usr/src/fred to /etc/fred .

    Finally, once the basename is patched up, we're home free, with a rename invocation.

  3. Here's one way to do it:

    ($old, $new) = @ARGV; # name them
    if (-d $new) { # new name is a directory, need to patch it up
        ($basename = $old) =~ 
    
    
    
    s#.*/##s; # get basename of $old
        $new .= "/$basename"; # and append it to new name
    }
    link($old,$new) || die "Cannot link $old to $new: $!";

    This program is identical to the previous program except for the very last line, because we're linking, not renaming.

  4. Here's one way to do it:

    if ($ARGV[0] eq "-s") { # wants a symlink
        $symlink++; # remember that
        
    
    shift(@ARGV); # and toss the -s flag
    }
    ($old, $new) = @ARGV; # name them
    if (-d $new) { # new name is a directory, need to patch it up
        ($basename = $old) =~ 
    
    
    
    s#.*/##s; # get basename of $old
        $new .= "/$basename"; # and append it to new name
    }
    if ($symlink) { # wants a symlink
        
    
    symlink($old,$new);
    } else { # wants a hard link
        
    
    link($old,$new);
    }

    The middle of this program is the same as the previous two exercises. What's new is the first few lines and the last few lines.

    The first few lines look at the first argument to the program. If this argument is -s , the scalar variable $symlink is incremented, resulting in a value of 1 for the variable. The @ARGV array is then shifted, removing the -s flag. If the -s flag isn't present, there's nothing to be done, and $symlink will remain undef . Shifting the @ARGV array occurs frequently enough that the @ARGV array is the default argument for shift ; that is, we could have said:

      shift;

    in place of

      shift(@ARGV);

    The last few lines look at the value of $symlink . It's going to be either 1 or undef , and based on that, we either symlink the files or link them.

  5. Here's one way to do it:

    foreach $f (<*>) {
        print "$f -> $where\n" if defined($where = 
    
    readlink($f));
    }

    The scalar variable $f is set in turn to each of the filenames in the current directory. For each name, $where gets set to the readlink() of that name. If the name is not a symlink, the readlink operator returns undef , yielding a false value for the if test, and the print is skipped. But when the readlink operator returns a value, the print displays the source and destination symlink values.