Finding all the links in a Unix file/directory path

F

freesoft12

Hi,

I am working on a Perl script that copies files from a log file. Some
of the files are links. The link however is in an intermediate
directory. For example, in a path /tmp/test_hier/b/f/of3.cpp, the
actual path is /tmp/test_hier/b/c/of3.cpp.

I have attached a DirGen.pm that creates the sample directory
hierarchy and a DirGen.t that prints out the information that the file
is a link.


My Questions:
1) Does anyone know how I can recursively trace the links so that I
copy the "exact" hierarchy? For example, I want to copy *everything*
in /tmp/test_hier underneath /tmp/copy/tmp/test_hier (verbatim).
2) The complication is that there might be arbitrary number of links
between the linked path and the actual path. How can I trace all of
them?

All help is appreciated!
Regards
John


--- DirGen.pm

# this package creates a sample directory structure
package DirGen;

sub new {
my $class = shift;
my $work_dir = shift;
my $self = {};
$self->{working_dir_} = $work_dir;
bless($self,$class);

# create a sample hieararchy underneath $work_dir
my @args = ("rm -rf $work_dir && mkdir -p $work_dir");
system(@args) ==0 or die "system command failed:$?";

# go to the working dir
chdir "$work_dir" or die "system command failed:$?";

# the test directory tree
# $work_dir/
# b/ - f -> c/ # f is a link to directory c/
# c/ - of3.cpp
#
my @dir_tree = ("mkdir -p b/c",
"touch b/c/of3.cpp",
"echo 4 > b/c/of3.cpp",
"cd b && ln -s c f");

$self->generate_test_hier_(\@dir_tree);

# access of3.cpp path via the directory link
my $path = "$work_dir/b/f/of3.cpp";
push(@{$self->{paths_}},$path);

return $self;
}

# This function creates a predefined directory hierarchy
sub generate_test_hier_ {
my $self = shift;
my $dir_tree_cmds = shift;
my @args = ();
foreach my $path (@$dir_tree_cmds) {
my @args = ($path);
system(@args) ==0 or die "system command failed:$?";
}
}

sub get_iterator {
my $self = shift;
my $pos = -1;
return sub {
return undef if ($pos > scalar(@{$self->{paths_}}));
return ${$self->{paths_}}[++$pos];
}
}

1;
----- end of DirGen.pm

------ DirGen.t

eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"$@"}' && eval 'exec
perl -w -S $0 $argv:q' if 0;
# This script tests DirGen.pm

require 5.006; # need perl version 5.6 or higher
use strict; # comment out these two
use diagnostics; # and '-w' switch, once testing is over
use File::Basename;
use Cwd qw(realpath);

use DirGen;

my $dirTreeGen = DirGen->new("/tmp/test_hier");

my $dir_it = $dirTreeGen->get_iterator();
while (my $path = $dir_it->()) {
my $target_dir = dirname($path);
my $orig_dir = realpath($target_dir);# realpath works only with
directories
if ($orig_dir ne $target_dir) {
print "$path is a link, the actual path is $orig_dir/".basename
($path)."\n";
}
}
-------- end of DirGen.t
 
S

smallpond

Hi,

I am working on a Perl script that copies files from a log file. Some
of the files are links. The link however is in an intermediate
directory. For example, in a path /tmp/test_hier/b/f/of3.cpp, the
actual path is /tmp/test_hier/b/c/of3.cpp.

I have attached a DirGen.pm that creates the sample directory
hierarchy and a DirGen.t that prints out the information that the file
is a link.

The test for a symbolic link in perl is: -l $name
my @dir_tree = ("mkdir -p b/c",
"touch b/c/of3.cpp",
"echo 4 > b/c/of3.cpp",
"cd b && ln -s c f");

To make a directory in perl: mkdir $dirname;
To create a symbolic link in perl: symlink OLDFILE,NEWFILE;
 
J

John

Looks like my question was not clear:

In my logfile, i see the following path: /tmp/test_hier/b/f/of3.cpp.
Since directory 'f' is a symbolic link to directory 'c', the actual
path is /tmp/test_hier/b/c/of3.cpp.

I want to copy the orig path /tmp/test_hier/b/f/of3.cpp to my target
directory: /tmp/copy/ . here is what I want to do:

1) Copy the actual file /tmp/test_hier/b/c/of3.cpp as /tmp/copy/tmp/
test_hier/b/c/of3.cpp
2) Create a link: /tmp/copy/tmp/test_hier/b/f -> /tmp/copy/tmp/
test_hier/b/c

Now /tmp/copy/tmp/test_hier/ is the same as /tmp/test_hier/. the
problems are:

1) 'realpath' just returns the actual file. It does not return how the
symbolic link is traced through the directories and the actual file is
found. I need that information.

2) there could an arbitrary number of links between the first symbolic
link file (/tmp/test_hier/b/f/of3.cpp) and the actual file i.e /tmp/
test_hier/b/f -> /tmp/test_hier/b/d -> /tmp/e -> /home/usr1/of3.cpp.

The problem: I have 2 paths in my hand: the symbolic link file ( /tmp/
test_hier/b/f/of3.cpp) and the actual file ( /home/usr1/of3.cpp).

Do any of you have any idea how to trace the intermediate symbolic
links?
Regards
John
 
J

Jürgen Exner

John said:
Looks like my question was not clear:

In my logfile, i see the following path: /tmp/test_hier/b/f/of3.cpp.
Since directory 'f' is a symbolic link to directory 'c', the actual
path is /tmp/test_hier/b/c/of3.cpp.

I want to copy the orig path /tmp/test_hier/b/f/of3.cpp to my target
directory: /tmp/copy/ . here is what I want to do:

1) Copy the actual file /tmp/test_hier/b/c/of3.cpp as /tmp/copy/tmp/
test_hier/b/c/of3.cpp
2) Create a link: /tmp/copy/tmp/test_hier/b/f -> /tmp/copy/tmp/
test_hier/b/c

So, if I understand correctly you want to copy the complete _structure_
of the the file tree, i.e. if a directory entry was a symlink in the
original then it should become a symlink in the copy, too.

I _think_ this is exactly the behaviour of File::Copy::Recursive. At
least the doc says

SymLinks
If your system supports symlinks then symlinks will be copied as
symlinks instead of as the target file. Perl's symlink() is used instead
of File::Copy's copy() You can customize this behavior by setting
$File::Copy::Recursive::CopyLink to a true or false value.

jue
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top