my own perl "dos->unix"/"unix->dos"

R

Robert Wallace

i made a dos to unix, unix to dos program catered for my own purposes.

it's seems to work fine. small program, 26 lines

anyone see any potential problems with it? do you have a better way to
do it?
my next step is to slip in some code to automatically "detect" whether
its a unix or dos file.

#!/usr/bin/perl -w
use strict;

#setting based on filename argument.
# if sym link is dos-unix or if sym link is unix-dos
my ($from, $to);
my $option=substr($0,rindex($0,'/')+1,length($0)-1); # $0 gives full
path. this code gives just filename
if ($option eq "dos-unix"){
$from="\015\012";
$to ="\012";
} elsif ($option eq "unix-dos"){
$from="[^\015]\012";
$from="[^\015]\012";
$to ="\015\012";
} else {
print "only sym links \"unix-dos\" and \"dos-unix\" are allowed\n";
}

foreach my $file (@ARGV){
my @output;
open READ, $file or die "Could not open file '$file' $!";
while (<READ>){
$_=~s/\Q$from/$to/;
push @output, $_;
}
close (READ);

open WRITE, ">$file" or die "Could not open output file '$file' $!";
print WRITE @output;
close (READ);
}
 
A

A. Sinan Unur

Robert Wallace said:
i made a dos to unix, unix to dos program catered for my own purposes. ....
anyone see any potential problems with it? do you have a better way to
do it?
#!/usr/bin/perl -w
use strict;

#setting based on filename argument.
# if sym link is dos-unix or if sym link is unix-dos
my ($from, $to);
my $option=substr($0,rindex($0,'/')+1,length($0)-1); # $0 gives full

If you want your script to work on computers without symlinks, you might
want to handle this using command line options. Also, the line below you
comment is not related to your comment. If you keep with this commenting
style, your comments and code can get really out of sync when the script
gets bigger.
if ($option eq "dos-unix"){
$from="\015\012";
$to ="\012";
} elsif ($option eq "unix-dos"){
$from="[^\015]\012";
$from="[^\015]\012";

Why the repeated assignment to $from?
$to ="\015\012";
} else {
print "only sym links \"unix-dos\" and \"dos-unix\" are allowed\n";
}

foreach my $file (@ARGV){
my @output;
open READ, $file or die "Could not open file '$file' $!";
while (<READ>){
$_=~s/\Q$from/$to/;
push @output, $_;
}
close (READ);

I would actually open a temp file (there is a module to do that safely
and cleanly), write my output to that file, and only delete the original
and rename the temp after everything is successfully completed. That
would keep the script's memory usage constant regardless of file size.

open WRITE, ">$file"
or die "Could not open output file '$file' $!";
print WRITE @output;
close (READ);
}

Ahem, if an error happens while you are writing to or closing the file,
you will have already clobbered the original. I don't see your script
asking the user if it is OK to nuke his file out of existence if the
conversion fails. Again, using a temporary file would handle this.

First, do no harm.

Sinan.
 
P

Paul Lalli

anyone see any potential problems with it? do you have a better way to
do it?
} elsif ($option eq "unix-dos"){
$from="[^\015]\012";
$to ="\015\012";
}
while (<READ>){
$_=~s/\Q$from/$to/;
push @output, $_;
}

Are you sure you don't want lookbehinds here? I haven't tried your code,
but it looks to me like you're going to end up replacing both \012 and
whatever character came before it with \015\012. I think you want to
search for \012 that was not preceded by \015, but don't actually match
(and therefore replace) whatever character did precede it. That involves
lookbehinds, I believe.

Paul Lalli
 
B

Ben Morrow

Robert Wallace said:
#!/usr/bin/perl -w
use strict;

use warnings;

is better than -w.
#setting based on filename argument.
# if sym link is dos-unix or if sym link is unix-dos
my ($from, $to);
my $option=substr($0,rindex($0,'/')+1,length($0)-1); # $0 gives full

Use File::Spec or File::Basename to do this sort of thing.
path. this code gives just filename

I try and keep code wrapped to a reasonable line length; part of doing
this means not putting long comments on the ends of lines.
if ($option eq "dos-unix"){
$from="\015\012";
$to ="\012";
} elsif ($option eq "unix-dos"){
$from="[^\015]\012";
$from="[^\015]\012";
$to ="\015\012";
} else {
print "only sym links \"unix-dos\" and \"dos-unix\" are allowed\n";

Use qq{}.
}

foreach my $file (@ARGV){
my @output;
open READ, $file or die "Could not open file '$file' $!";

Use lexical filehandles, and scope them rather than explicitly closing
where you can.

open my $READ, $file or die...;
while (<READ>){
$_=~s/\Q$from/$to/;
push @output, $_;
}
close (READ);

open WRITE, ">$file" or die "Could not open output file '$file' $!";
print WRITE @output;
close (READ);

ITYM close (WRITE)?

Ben
 
G

Gunnar Hjalmarsson

Paul said:
} elsif ($option eq "unix-dos"){
$from="[^\015]\012";
$to ="\015\012";
}

while (<READ>){
$_=~s/\Q$from/$to/;
push @output, $_;
}

Are you sure you don't want lookbehinds here? I haven't tried your
code, but it looks to me like you're going to end up replacing both
\012 and whatever character came before it with \015\012. I think
you want to search for \012 that was not preceded by \015, but
don't actually match (and therefore replace) whatever character did
precede it. That involves lookbehinds, I believe.

Or capturing:

$from = "([^\015])\012";

....

$_ =~ s/$from/$1$to/;

(quoting meta seems not to be correct)
 
M

Michele Dondi

i made a dos to unix, unix to dos program catered for my own purposes.

it's seems to work fine. small program, 26 lines

Have you ever heard of a (programmer's) virtue called lazyness?
Whenever I'm too lazy to remember which is which and I do not have any
particular requirement but converting to the native convention of the
OS I'm using, I resort to

perl -lpi -e '' <file(s)>

Well that is under Linux, under Win I have to do

perl -lpi.bak -e "" <file(s)>

and

perl -lpi.bak -e "BEGIN{@ARGV=map glob($_),@ARGV}" <file(s)>

if I need to use wildcards. (yes, I know there's an AS executable that
does shell wildcard expansion!)

My program is 1 line only! It is not equivalent to yours though...
;-)


HTH,
Michele
 

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,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top