#!/usr/bin/perl -w ######################################################################### # # # Create a Tree of Symbolic Links # # Copyright (C) 2002-04, John Zaitseff # # # ######################################################################### # Author: John Zaitseff # Date: 3rd December, 2004 # Version: 1.3 # This script creates a tree, in the current directory, of symbolic links # to files that are located in other places. # # Syntax: # symlink-tree sourcedir ... # This program, including associated files, is free software. You may # distribute it and/or modify it under the terms of the GNU General Public # License as published by the Free Software Foundation; either Version 2 # of the license, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ######################################################################### # Configuration parameters and default values use strict; # Enforce better programming habits use File::Find (); # Directory tree traversal (our $O = $0) =~ s,^.*/,,; # Script name (without path) our $version = "1.3"; # Script version # Function prototypes sub showusage(); sub showversion(); sub showcmdlerr(@); sub wanted($); ######################################################################### # Process command-line arguments while ($_ = $ARGV[0]) { last if (! /^-/); shift @ARGV; last if ($_ eq '--'); # Split combined short-form options into single arguments if (/^-(\w{2,})/) { my @args = split //, $1; foreach my $arg (@args) { $arg = "-$arg"; } unshift @ARGV, @args; next; } # Process command-line options if (($_ eq "--help") || ($_ eq "-h") || ($_ eq "-?")) { showusage(); } elsif (($_ eq "--version") || ($_ eq "-V")) { showversion(); } else { showcmdlerr("Unrecognised option: $_"); } } # Check that at least one parameter was given showcmdlerr("Missing parameters") if $#ARGV < 0; # Check that all parameters given are actually valid directories foreach $_ (@ARGV) { # Remove trailing slashes from the paramater (our $srcdir = $_) =~ s/\/+$//; if (! -e $_) { die "$O: $_: $!\n"; } elsif (! -d _) { die "$O: $_: Not a directory\n"; } # Check for some silly things... If the user wishes to shoot himself # in the foot, he can get around these "restrictions" if (($srcdir eq ".") || ($srcdir eq "..") || ($srcdir eq "")) { die "$O: $_: Invalid directory\n"; } } ######################################################################### # Main program File::Find::find({wanted => \&wanted, follow => 0, no_chdir => 1}, @ARGV); exit(0); sub wanted($) { my $file = $_; my $dir = $File::Find::dir; my $topdir = $File::Find::topdir; my $destfile; my $destdir; my $srcdir; if (-d $file) { if ($file ne $topdir) { # $file is a subdirectory within one of the specified # directories. Create a matching subdirectory in our # destination (the current directory) } $destdir = substr($file, length($topdir) + 1); mkdir $destdir; } } else { $destfile = substr($file, length($topdir) + 1); $srcdir = substr($dir, length($topdir)); # Check if the source file is an absolute pathname or not if ($file =~ /^\//) { symlink($file, $destfile); } else { $srcdir =~ s/[^\/]//g; $srcdir =~ s/\//..\//g; symlink($srcdir . $file, $destfile); } } } ######################################################################### # Display usage information sub showusage() { print <<"DATAEND" $O v$version: Create a Tree of Symbolic Links Copyright (C) 2002-04, John Zaitseff. This program creates a tree, in the current directory, of symbolic links to files that are located in other places. Syntax: $O sourcedir ... DATAEND ; exit(0); } ######################################################################### # Display program version information sub showversion() { print <<"DATAEND" $O v$version: Create a Tree of Symbolic Links Copyright (C) 2002-04, John Zaitseff. This program, including associated files, is distributed under the GNU General Public License. See the file COPYING for more information. DATAEND ; exit(0); } ######################################################################### # Show an error message relating to the command-line and terminate sub showcmdlerr(@) { map { warn "$O: $_\n" } @_; die "\nUsage:\n" . " $O sourcedir ...\n"; }