Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Need help with a Perl script written to move user data 2

Status
Not open for further replies.

gsr0

Programmer
Dec 1, 2004
6
CA
My situation is this: My school used to have their student/faculty login system setup, so each user loged in with their full name "First Last". This 'full name' was actually a psydonym for the real UNIX username, which was u character, followed by 3-5 addititonal digits (ie u881).

We have since upgraded to a new server, and while doing so, decided to change the real unix usernames, from numbers, to a short version of the user name

Gabriel Rigg, u881 becomes Gabriel Rigg, grigg

I have two files in my posession:
1) a file containing old usernumbers, and full names:
-------------------------usrbynum.txt---------------------
Code:
u880             name: Gabe Girard
u881             name: Gabriel Rigg
u882             name: Genna Bourget
... for about 263 of them
----------------------------EOF----------------------------

and 2) a file containing new shortnames, and full names

-------------------------srnames.txt-----------------------
Code:
fkasierderrick::1333:20::::Freya Kasier Derrick
grigg::1460:20::::Gabriel Rigg
omeara::1025:20::::Gary O'Meara
---------------------------EOF-----------------------------

There are a few issues to deal with. First, not everyone in short/full is in num/full, but I can deal with that later. However, here is my code:

Code:
#!/usr/bin/perl

$oldserv = "./testing";
$newserv = "./testing2";
$usernumfile = "./usrbynum.txt";
$usershortfile = "./srnames.txt";

open USERNUMS, "< $usernumfile" or die "$!";     
open SHORTNAMES, "< $usershortfile" or die "$!";# open file with user 

# loop through all lines of shortnames
while (<SHORTNAMES>) {                
    my ($longname,$shortname) = (split /:/)[7,0];            
# seperate by those ugly colen

    $finishedusers{$longname} = $shortname;
    chomp %finishedusers;
}

my %lookup;        # Hash %lookup
while(<USERNUMS>) {    # loop through file with user numbers
    ($uid) = /(u\d{3,5})/;    # User ID find yes
    ($longname2) = /([A-Z]\w+)/;
    chomp $longname2;
    # Setup hash %lookup with keys "Long Name"=> "usernum"
    $lookup{$longname2} = $uid;
}

while (($longname2, $uid) = each(%lookup)) {
    next unless exists $finishedusers{$longname2};
    system ("cp '$oldserv/$uid/Documents/*' '$newserv/$finishedusers{$longname2}/Documents/'");
    print "Copying Files for $finishedusers{longname2}";
}

close USERNUMS;
close SHORTNAMES;

To test whether or not the hashes of the different files were working, I commented most of the code out, and told it to to print to the screen. For example:

Code:
while (<SHORTNAMES>) {         # loop through all lines of shortnames
    my ($longname,$shortname) = (split /:/)[7,0];            # seperate by those ugly colen
        $finishedusers{$longname} = $shortname;
    chomp %finishedusers;
}
while (($templong,$tempshort) = each(%finishedusers)) {
        print "long: $templong \n short: $tempshort \n\n
}
For both of the files and their while() statements used to extract data for the hashes, they printed the exact correct statements (even the newlines added up, so there were none because of the chomp). So, I know that, individually at least, these statements work.

The final few lines of the code is supposed to match shortnames to old usernumbers, via a matching long name (since its the shared constant between the files), and move all the files from the old usernumber/Directory to the short/Directory.

I added 'use strict; use warnings;', and got the following output:
Global symbol "$oldserv" requires explicit package name at doctrans2.pl line 6.
Global symbol "$newserv" requires explicit package name at doctrans2.pl line 7.
Global symbol "$usernumfile" requires explicit package name at doctrans2.pl line 8.
Global symbol "$usershortfile" requires explicit package name at doctrans2.pl line 9.
Global symbol "$usernumfile" requires explicit package name at doctrans2.pl line 11.
Global symbol "$usershortfile" requires explicit package name at doctrans2.pl line 12.
Global symbol "%finishedusers" requires explicit package name at doctrans2.pl line 15.
Global symbol "%finishedusers" requires explicit package name at doctrans2.pl line 16.
Global symbol "$uid" requires explicit package name at doctrans2.pl line 21.
Global symbol "$longname2" requires explicit package name at doctrans2.pl line 22.
Global symbol "$longname2" requires explicit package name at doctrans2.pl line 23.
Global symbol "$longname2" requires explicit package name at doctrans2.pl line 24.
Global symbol "$uid" requires explicit package name at doctrans2.pl line 24.
Global symbol "$longname2" requires explicit package name at doctrans2.pl line 27.
Global symbol "$uid" requires explicit package name at doctrans2.pl line 27.
Global symbol "%finishedusers" requires explicit package name at doctrans2.pl line 28.
Global symbol "$longname2" requires explicit package name at doctrans2.pl line 28.
Global symbol "$oldserv" requires explicit package name at doctrans2.pl line 29.
Global symbol "$uid" requires explicit package name at doctrans2.pl line 29.
Global symbol "$newserv" requires explicit package name at doctrans2.pl line 29.
Global symbol "%finishedusers" requires explicit package name at doctrans2.pl line 29.
Global symbol "$longname2" requires explicit package name at doctrans2.pl line 29.
Global symbol "%finishedusers" requires explicit package name at doctrans2.pl line 30.
Execution of doctrans2.pl aborted due to compilation errors.

However, without use strict and use warnings, the code execute with no errors, but no results.

Expected result was that a file ./testing/u881/Documents/test.txt would be moved to ./testing2/grigg/Documents/ . However, it does not get moved (obviously).

Any suggestions?
 
Please note that, although I am a student at this school, I am a friend with the sys admin, and I am helping with this merge for that reason. It is not homework (just thought I should clear any doubt, because I saw the note about homework).
 
1. You're getting those error messages about global variables because strict requires that you declare your variables with my, and obviously you have many vars that are not declared this way. I suggest you leave use strict in and declare all your variables with my.

2. Instead of chomping vars, chomp records as you read them from a file, e.g
while (<SHORTNAMES>) {
chomp;


and
while (<USERNUMS>) {
chomp;


chomp with no argument chomps $_, the current input record. Get rid of the chomp statements on the vars as you won't need them.

3. Variable names do not interpolate inside single quotes.
In system ("cp '$oldserv/$uid/Documents/*' '$newserv/$finishedusers{$longname2}/Documents/'"); $oldserv,
$uid, $newserv,
and $finishedusers are just strings, not the variables they represent. Get rid of the single quotes.

4. I'm not sure I understand what you're doing as far as moving files, but the above should give you plenty to get started with.

HTH


 
If you are using strict, then all the variables that were complained about need to be changed in the following way:

EX:

$testvar

TO

$main::testvar

Notice the main:: inserted between the "$" and the variable name.

That should solve the issue.


Michael Libeson
 
With respect to mlibeson above - I would suggest that declaring the variables like this:

my $testvar;

is a better solution than using $main::testvar

Mike

To err is human,
but to really foul things up -
you require a man Mike.

Want to get great answers to your Tek-Tips questions? Have a look at faq219-2884

 
OK, I've edited the code a bit more, using proper syntax with use strict. I am now getting a syntax error, and the script still wont work.

New Code:
Code:
#!/usr/bin/perl -w
use strict;
use File::NCopy qw(copy);

my $oldserv = "./testing";
my $newserv = "./testing2";
my $usernumfile = "./usrbynum.txt";
my $usershortfile = "./srnames.txt";

my %finishedusers;
open USERNUMS, "< $usernumfile" or die "$!";     
open SHORTNAMES, "< $usershortfile" or die "$!";# open file with user 
while (<SHORTNAMES>) {                # loop through all lines of shortnames
	chomp;
	my ($longname,$shortname) = (split /:/)[7,0];            # seperate by those ugly colen
	my $finishedusers{$longname} = $shortname;
}

my %lookup;        # Hash %lookup
while(<USERNUMS>) {    # loop through file with user numbers
	chomp;
	my ($uid) = /(u\d{3,5})/;	# User ID find yes
	my ($longname2) = /([A-Z]\w+)/;
	$lookup{$longname2} = $uid;       # Setup hash %lookup with keys "Long Name"=> "usernum"
}
while (($longname2, $uid) = each(%lookup)) {
	next unless exists $finishedusers{$longname2};
	my $old2copy = "$oldserv/$uid/Documents/*";
	my $new2paste = "$newserv/$finishedusers{$longname2}/Documents/";
	copy $old2copy, $new2paste;
	print "Copying Files for $finishedusers{longname2}";
}

close USERNUMS;
close SHORTNAMES;

And here is the error I get:

gsr@pengo perlcode $ perl *.pl
syntax error at doctrans2.pl line 16, near "$finishedusers{"
Execution of doctrans2.pl aborted due to compilation errors.
 
Get rid of the my in the following line:
my $finishedusers{$longname} = $shortname;

You've already declared %finishedusers with my earlier in the script. You don't declare individual hash elements.
 
I changed the code accordingly:

Code:
#!/usr/bin/perl -w
use strict;
use File::NCopy qw(copy);

my $oldserv = "./testing";
my $newserv = "./testing2";
my $usernumfile = "./usrbynum.txt";
my $usershortfile = "./srnames.txt";

my %finishedusers;
open USERNUMS, "< $usernumfile" or die "$!";     
open SHORTNAMES, "< $usershortfile" or die "$!";# open file with user 
while (<SHORTNAMES>) {                # loop through all lines of shortnames
	chomp;
	my ($longname,$shortname) = (split /:/)[7,0];            # seperate by those ugly colen
	$finishedusers{$longname} = $shortname;
}

my %lookup;        # Hash %lookup
while(<USERNUMS>) {    # loop through file with user numbers
	chomp;
	my ($uid) = /(u\d{3,5})/;	# User ID find yes
	my ($longname2) = /([A-Z]\w+)/;
	$lookup{$longname2} = $uid;       # Setup hash %lookup with keys "Long Name"=> "usernum"
}
while (($longname2,$uid) = each(%lookup)) {
	next unless exists $finishedusers{$longname2};
	my $old2copy = "$oldserv/$uid/Documents/*";
	my $new2paste = "$newserv/$finishedusers{$longname2}/Documents/";
	copy $old2copy, $new2paste;
	print "Copying Files for $finishedusers{$longname2}";
}

close USERNUMS;
close SHORTNAMES;

and I now get this error:

Code:
Global symbol "$longname2" requires explicit package name at doctrans2.pl line 26.
Global symbol "$uid" requires explicit package name at doctrans2.pl line 26.
Global symbol "$longname2" requires explicit package name at doctrans2.pl line 27.
Global symbol "$uid" requires explicit package name at doctrans2.pl line 28.
Global symbol "$longname2" requires explicit package name at doctrans2.pl line 29.
Global symbol "$longname2" requires explicit package name at doctrans2.pl line 31.
Execution of doctrans2.pl aborted due to compilation errors.

even though $longname2 and $uid were both predeclared with my, only a few lines up!
 
$longname2 and $uid were both predeclared with my, only a few lines up!
Yes, but they are declared inside the while(<USERNUMS>) loop, so their scope is limited to that loop and they are not known outside it. If you need them to be available in the next loop, declare them before the while(<USERNUMS>) loop, where you declare %lookup.

If you haven't read the documentation on my you should do so. Either go to and search for my, or use perldoc -f my at the command prompt.
 
Thanks for both suggestions. The script now works perfectly!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top