string assignment and concatenation

J

Justin C

#!/usr/bin/perl

use warnings ;
use strict ;
use File::Copy ;

open ( CSV, '<', "forthcoming_releases.csv" )
or die "Cannot open csv file: $!" ;

foreach ( <CSV> ) {
chomp ;
if ( my ($newname, undef, undef, undef, $oldname) = split /,/ ) {
print $newname, "\t", $oldname, "\n" ;
$newname .= ".jpg" ;
$oldname = $oldname . ".jpg" ;
print $newname, "\t", $oldname, "\n" ;
move ( $oldname, $newname ) ;
}
}


The two print statements are there to help me debug, but they're no help!

A sample of the CSV:

1,AC/DC,2003 Logo,TS,ts_ac_2003
2,AC/DC,A5 Highway Fire,JO,jo_ac_a5highw
3,AC/DC,Album Stiff,TS,ts_ac_albumst
4,AC/DC,Amp,TS,ts_ac_amp
5,AC/DC,Angus,TS,ts_ac_angusb
6,AC/DC,Angus Caricature,SB,sb_ac_angus
7,AC/DC,Angus Comin' At Ya,HF,hf_ac_angusco
8,AC/DC,Angus For Those,TS,ts_ac_angusf
9,AC/DC,Angus Head,RP,rp_ac_angushe
10,AC/DC,Angus Let,TS,ts_ac_angusle


The last field in the CSV is the current filename without the .jpg,
the first field is a unique number, I'm trying to name these files
sequentially, but with .jpg

As you can see I've tried two methods for concatenation and neither
seems to do what I'd expect. $oldname never gets .jpg appended and
$newname starts of being .jpg, then .jpgpj, and lastly (for 3 digit
numbers) .jpgjpg. I can see what is happening with $newname but don't
understand why.

If someone could point me at an explanation here I'd be grateful. I've
never had trouble with assignment before, well, not like this. The code
looks right to me but obviously I know nothing!

Thanks for any help you can give.


Justin.
 
D

Dean G.

Justin said:
#!/usr/bin/perl

use warnings ;
use strict ;
use File::Copy ;

open ( CSV, '<', "forthcoming_releases.csv" )
or die "Cannot open csv file: $!" ;

foreach ( <CSV> ) {
chomp ;
if ( my ($newname, undef, undef, undef, $oldname) = split /,/ ) {
print $newname, "\t", $oldname, "\n" ;
$newname .= ".jpg" ;
$oldname = $oldname . ".jpg" ;
print $newname, "\t", $oldname, "\n" ;
move ( $oldname, $newname ) ;
}
}


The two print statements are there to help me debug, but they're no help!

A sample of the CSV:

1,AC/DC,2003 Logo,TS,ts_ac_2003
2,AC/DC,A5 Highway Fire,JO,jo_ac_a5highw
3,AC/DC,Album Stiff,TS,ts_ac_albumst
4,AC/DC,Amp,TS,ts_ac_amp
5,AC/DC,Angus,TS,ts_ac_angusb
6,AC/DC,Angus Caricature,SB,sb_ac_angus
7,AC/DC,Angus Comin' At Ya,HF,hf_ac_angusco
8,AC/DC,Angus For Those,TS,ts_ac_angusf
9,AC/DC,Angus Head,RP,rp_ac_angushe
10,AC/DC,Angus Let,TS,ts_ac_angusle


The last field in the CSV is the current filename without the .jpg,
the first field is a unique number, I'm trying to name these files
sequentially, but with .jpg

As you can see I've tried two methods for concatenation and neither
seems to do what I'd expect. $oldname never gets .jpg appended and
$newname starts of being .jpg, then .jpgpj, and lastly (for 3 digit
numbers) .jpgjpg. I can see what is happening with $newname but don't
understand why.

If someone could point me at an explanation here I'd be grateful. I've
never had trouble with assignment before, well, not like this. The code
looks right to me but obviously I know nothing!

Thanks for any help you can give.

I'm not sure what to say, since it seems to work for me. I have
commented out the move line, as I obviously don't have the same files,
but the prints seem to print what you are looking for.

I'm using v5.8.7.

What does your output look like ?

Also, since you don't seem to be moving anything across filesystem
boundaries, you could also use the rename function instead of
File::Copy

Dean G.
 
D

dt

Justin said:
#!/usr/bin/perl

use warnings ;
use strict ;
use File::Copy ;

open ( CSV, '<', "forthcoming_releases.csv" )
or die "Cannot open csv file: $!" ;

foreach ( <CSV> ) {
chomp ;
if ( my ($newname, undef, undef, undef, $oldname) = split /,/ ) {
print $newname, "\t", $oldname, "\n" ;
$newname .= ".jpg" ;
$oldname = $oldname . ".jpg" ;
print $newname, "\t", $oldname, "\n" ;
move ( $oldname, $newname ) ;

Do you mean to use rename here?

perldoc -f rename

From 'perldoc perlfaq5',

How can I reliably rename a file?

If your operating system supports a proper mv(1) utility or its functional
equivalent, this works:

rename($old, $new) or system("mv", $old, $new);

It may be more portable to use the File::Copy module instead. You just copy
to the new file to the new name (checking return values), then delete the
old one. This isn't really the same semantically as a rename(), which
preserves meta-information like permissions, timestamps, inode info, etc.

Newer versions of File::Copy export a move() function.

dt
 
J

Justin C

dt said:
Do you mean to use rename here?

perldoc -f rename

From 'perldoc perlfaq5',

How can I reliably rename a file?

If your operating system supports a proper mv(1) utility or its functional
equivalent, this works:

rename($old, $new) or system("mv", $old, $new);

It may be more portable to use the File::Copy module instead. You just copy
to the new file to the new name (checking return values), then delete the
old one. This isn't really the same semantically as a rename(), which
preserves meta-information like permissions, timestamps, inode info, etc.

What part of my post didn't you understand that lead you to post this?
Newer versions of File::Copy export a move() function.

Ooh! Smart cookie, did you even read what I posted?
 
J

Justin C

Dean G. said:
I'm not sure what to say, since it seems to work for me. I have
commented out the move line, as I obviously don't have the same files,
but the prints seem to print what you are looking for.

I'm using v5.8.7.

5.8.4, but I can't believe that there is a bug here. I can understand
them in the far reaches of rarely used bits of perl, but assignment?
What does your output look like ?

A sample is below but the upshot is: .jpg doesn't get appended to
$oldname and $newname contains just .jpg as here:

1 ts_ac_2003
..jpgg ts_ac_2003
2 jo_ac_a5highw
..jpgg jo_ac_a5highw
3 ts_ac_albumst
..jpgg ts_ac_albumst
4 ts_ac_amp
..jpgg ts_ac_amp
5 ts_ac_angusb
..jpgg ts_ac_angusb
6 sb_ac_angus
..jpgg sb_ac_angus
7 hf_ac_angusco
..jpgg hf_ac_angusco
8 ts_ac_angusf
..jpgg ts_ac_angusf
9 rp_ac_angushe
..jpgg rp_ac_angushe
10 ts_ac_angusle
..jpgpg ts_ac_angusle

Also, since you don't seem to be moving anything across filesystem
boundaries, you could also use the rename function instead of
File::Copy

Thanks for the pointer. I still need to get the assignment right first
though. I've stared at it until I can't even see the code anymore but
can't see anything wrong with it.

As an aside, the perl install on the computer in question serves cgi for
our in-house web-site without trouble so I'm inclined to think the
install is OK.... Hmmmm.... 'tis amd64 version of Debian stable though -
which is unsupported - could have some bugs I suppose.
 
X

xhoster

As you can see I've tried two methods for concatenation and neither
seems to do what I'd expect. $oldname never gets .jpg appended and
$newname starts of being .jpg, then .jpgpj, and lastly (for 3 digit
numbers) .jpgjpg. I can see what is happening with $newname but don't
understand why.

It sounds to me like you have "\r" (aka ^M) or other special characters in
your csv file. When you print such strings to your terminal, it causes
weird things to happen. Instead of just printing to the sceen, redirect
output to a file and open it in a good text editor.

Xho
 
D

Dean G.

Justin said:
A sample is below but the upshot is: .jpg doesn't get appended to
$oldname and $newname contains just .jpg as here:

1 ts_ac_2003
.jpgg ts_ac_2003
2 jo_ac_a5highw
.jpgg jo_ac_a5highw
3 ts_ac_albumst
.jpgg ts_ac_albumst
4 ts_ac_amp
.jpgg ts_ac_amp
5 ts_ac_angusb
.jpgg ts_ac_angusb
6 sb_ac_angus
.jpgg sb_ac_angus
7 hf_ac_angusco
.jpgg hf_ac_angusco
8 ts_ac_angusf
.jpgg ts_ac_angusf
9 rp_ac_angushe
.jpgg rp_ac_angushe
10 ts_ac_angusle
.jpgpg ts_ac_angusle



Thanks for the pointer. I still need to get the assignment right first
though. I've stared at it until I can't even see the code anymore but
can't see anything wrong with it.

As an aside, the perl install on the computer in question serves cgi for
our in-house web-site without trouble so I'm inclined to think the
install is OK.... Hmmmm.... 'tis amd64 version of Debian stable though -
which is unsupported - could have some bugs I suppose.

In that case, maybe Xho (see message below about embedded control
characters) may be on to something. Try adding

s/[\cA-\cZ]//g;

after the chomp and before the if to strip out the control chars.


Dean G.
 
D

DJ Stunks

Justin said:
#!/usr/bin/perl

use warnings ;
use strict ;
use File::Copy ;

open ( CSV, '<', "forthcoming_releases.csv" )
or die "Cannot open csv file: $!" ;

foreach ( <CSV> ) {
chomp ;
if ( my ($newname, undef, undef, undef, $oldname) = split /,/ ) {
print $newname, "\t", $oldname, "\n" ;
$newname .= ".jpg" ;
$oldname = $oldname . ".jpg" ;
print $newname, "\t", $oldname, "\n" ;
move ( $oldname, $newname ) ;
}
}


1,AC/DC,2003 Logo,TS,ts_ac_2003
2,AC/DC,A5 Highway Fire,JO,jo_ac_a5highw
3,AC/DC,Album Stiff,TS,ts_ac_albumst
4,AC/DC,Amp,TS,ts_ac_amp
5,AC/DC,Angus,TS,ts_ac_angusb
6,AC/DC,Angus Caricature,SB,sb_ac_angus
7,AC/DC,Angus Comin' At Ya,HF,hf_ac_angusco
8,AC/DC,Angus For Those,TS,ts_ac_angusf
9,AC/DC,Angus Head,RP,rp_ac_angushe
10,AC/DC,Angus Let,TS,ts_ac_angusle

your assignment seems fine.

I would use a module to simplify things:

#!/usr/bin/perl

use warnings;
use strict;

use Text::CSV::Simple;

my $parser = Text::CSV::Simple->new;
$parser->field_map(qw/id null null null old/);

for my $line ( $parser->read_file(\*DATA) ) {
printf "rename %s.jpg to %d.jpg\n", @{ $line }{'old','id'};
}

__DATA__
1,AC/DC,2003 Logo,TS,ts_ac_2003
2,AC/DC,A5 Highway Fire,JO,jo_ac_a5highw
3,AC/DC,Album Stiff,TS,ts_ac_albumst
4,AC/DC,Amp,TS,ts_ac_amp
5,AC/DC,Angus,TS,ts_ac_angusb
6,AC/DC,Angus Caricature,SB,sb_ac_angus
7,AC/DC,Angus Comin' At Ya,HF,hf_ac_angusco
8,AC/DC,Angus For Those,TS,ts_ac_angusf
9,AC/DC,Angus Head,RP,rp_ac_angushe
10,AC/DC,Angus Let,TS,ts_ac_angusle

-jp
 
D

dt

Justin said:
What part of my post didn't you understand that lead you to post this?

The part I didn't understand were the parts you were complaining about.

Those parts work fine for me.

I took a WAG you needed some help elsewhere.
Ooh! Smart cookie, did you even read what I posted?

Yes, I downloaded it and ran it, too. Works fine for me.

Quit sounding like an ungrateful sloth and accept the help in
the spirit it was given.

-dt
 
P

Paul Lalli

dt said:
Quit sounding like an ungrateful sloth and accept the help in
the spirit it was given.

What help? The OP posted code that used File::Copy's move() function.
You posted a response that told him he meant to use Perl's built-in
rename() function, then copy and pasted a piece of documentation that
says to use File::Copy's move() function.

There was zero content to your post.

Paul Lalli
 
J

Justin C

It sounds to me like you have "\r" (aka ^M) or other special characters in
your csv file. When you print such strings to your terminal, it causes
weird things to happen. Instead of just printing to the sceen, redirect
output to a file and open it in a good text editor.

I thought I'd already posted a reply to this but it's not showing on my
news server.

Yes, you are correct, it's stray ^M on each line. I've removed them
using the method proposed by Dean. The (slightly) weird thing is I'd
already opened the CSV file in vi and seen nothing, but a pipe of the
output readily showed the stray control chars.

Thank you Xho, and Dean, for your help with this.
 
P

Peter J. Holzer

Yes, you are correct, it's stray ^M on each line. I've removed them
using the method proposed by Dean. The (slightly) weird thing is I'd
already opened the CSV file in vi and seen nothing, but a pipe of the
output readily showed the stray control chars.

You probably using vim (or another of the modern vi clones, like nvi or
elvis) instead of the real vi.

Vim goes to great lengths to guess the file format (line endings,
encoding, ...) when opening a file. So a file opened in vim will almost
always look correct, and the only hint will be the string "[dos]" or
"[converted]" in the status line. You can then enter ":set" to find out
what format the file was in (look for "fileformat" and "fileencoding").
This is nice if you want to edit files in different formats, as it will
usually "just work", but less nice if you want to use vim as a data
inspection tool.

When I suspect encoding issues I usually rely on good old "od -c" to get
an ASCII/octal dump (which is mostly habit - actually I find the output
of "hd" more readable).

hp
 

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,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top