Book HomeLearning Perl, 3rd EditionSearch this book

A.12. Answers to Chapter 13 Exercises

  1. Here's one way to do it:

    unlink @ARGV;

    ...or, if you want to warn the user of any problems:

    foreach (@ARGV) {
      unlink $_ or warn "Can't unlink '$_': $!, continuing...\n";
    }

    Here, each item from the command-invocation line is placed individually into $_, which is then used as the argument to unlink. If something goes wrong, the warning gives the clue about why.

  2. Here's one way to do it:

    use File::Basename;
    use File::Spec;
    
    my($source, $dest) = @ARGV;
    
    if (-d $dest) {
      my $basename = basename $source;
      $dest = File::Spec->catfile($dest, $basename);
    }
    
    rename $source, $dest
      or die "Can't rename '$source' to '$dest': $!\n";

    The workhorse in this program is the last statement, but the remainder of the program is necessary when we are renaming into a directory. First, after declaring the modules we're using, we name the command-line arguments sensibly. If $dest is a directory, we need to extract the basename from the $source name and append it to the directory ($dest). Finally, once $dest is patched up if needed, the rename does the deed.

  3. Here's one way to do it:

    use File::Basename;
    use File::Spec;
    
    my($source, $dest) = @ARGV;
    
    if (-d $dest) {
      my $basename = basename $source;
      $dest = File::Spec->catfile($dest, $basename);
    }
    
    link $source, $dest
      or die "Can't link '$source' to '$dest': $!\n";

    As the hint in the exercise description said, this program is much like the previous one. The difference is that we'll link rather than rename. If your system doesn't support hard links, you might have written this as the last line:

    print "Would link '$source' to '$dest'.\n";
  4. Here's one way to do it:

    use File::Basename;
    use File::Spec;
    
    my $symlink = $ARGV[0] eq '-s';
    shift @ARGV if $symlink;
    
    my($source, $dest) = @ARGV;
    if (-d $dest) {
      my $basename = basename $source;
      $dest = File::Spec->catfile($dest, $basename);
    }
    
    if ($symlink) {
      symlink $source, $dest
        or die "Can't make soft link from '$source' to '$dest': $!\n";
    } else {
      link $source, $dest
        or die "Can't make hard link from '$source' to '$dest': $!\n";
    }

    The first few lines of code (after the two use declarations) look at the first command-line argument, and if it's "-s", we're making a symbolic link, so we note that as a true value for $symlink. If we saw that "-s", we then need to get rid of it (in the next line). The next few lines are cut-and-pasted from the previous exercise answers. Finally, based on the truth of $symlink, we'll choose either to create a symbolic link or a hard link. We also updated the dying words to make it clear which kind of link we were attempting.

  5. Here's one way to do it:

    foreach (<.* *>) {
      my $dest = readlink $_;
      print "$_ -> $dest\n" if defined $dest;
    }

    Each item resulting from the glob ends up in $_ one by one. If the item is a symbolic link, then readlink returns a defined value, and the location is displayed. If not, then the condition fails, and we skip over it.



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.