Add Extension to files in a directory

D

deepak p

Hello,

I'm trying to add an extension (.sql) to all files whose names begin
with 'xa' in a specified directory. The files previously do not have
an extension. Hence, my goal is to rename file 'xaa' to
'xaa.sql'..likewise 'xab' to 'xab.sql'

I wrote a simple perl script to do this, but its not renaming the
files, and would appreciate any guidance anyone can suggest. Pasted
below is my script and the message printed to STDOUT. Thank you in
advance. At the moment, I'm developing it on SunOS running perl 5.61
but would need to be able to run it on Win32 as well, so would prefer
not having to make any OS system calls.

Deepak

----Script---
#!/usr/bin/perl -w

use strict;
my $Dir = "/home/aaa/datafiles/2003_08_28";
my $Debug = 1;

opendir(DIR, $Dir) or die "Can't open directory $Dir $! \n";
my @filenames = readdir(DIR);
@filenames = grep /^xa/, @filenames;
closedir(DIR);

my $counter = 0;
my ($filenames, $filename) = "";

if ($Debug == 1) {
foreach (@filenames) {
print "FileName $counter \t $filenames[$counter] \n";
$counter++;
}
}
my $dot = ".";
my $sql = "sql";

foreach $filename (@filenames) {
rename($filename, $filename.$sql) or warn "Couldn't rename $filename
to $filename$sql $! \n";
}

------Results printed to STDOUT-----

FileName 0 xaa
FileName 1 xab
FileName 2 xac
FileName 3 xad
FileName 4 xae
Couldn't rename xaa to xaa.sql No such file or directory
Couldn't rename xab to xab.sql No such file or directory
Couldn't rename xac to xac.sql No such file or directory
Couldn't rename xad to xad.sql No such file or directory
Couldn't rename xae to xae.sql No such file or directory
 
G

Greg Bacon

: I'm trying to add an extension (.sql) to all files whose names begin
: with 'xa' in a specified directory. The files previously do not have
: an extension. Hence, my goal is to rename file 'xaa' to
: 'xaa.sql'..likewise 'xab' to 'xab.sql'
:
: I wrote a simple perl script to do this, but its not renaming the
: files, and would appreciate any guidance anyone can suggest. Pasted
: below is my script and the message printed to STDOUT. Thank you in
: advance. At the moment, I'm developing it on SunOS running perl 5.61
: but would need to be able to run it on Win32 as well, so would prefer
: not having to make any OS system calls.

You made the easy mistake of forgetting to qualify your filenames
with their parent directory. See below for a fix and other
stylistic cleanup:

#! /usr/bin/perl

use warnings;
use strict;

my $Dir = "/home/aaa/datafiles/2003_08_28";
my $Debug = 1;

opendir DIR, $Dir or die "$0: opendir $Dir: $!\n";
my @filenames = map "$Dir/$_", grep /^xa/, readdir DIR;
closedir(DIR);

if ($Debug == 1) {
my $counter = 0;

for (@filenames) {
print "FileName $counter \t $_\n";
$counter++;
}
}

foreach my $old (@filenames) {
my $new = "$old.sql";
rename $old => $new or warn "$0: rename $old => $new: $!\n";
}

Hope this helps,
Greg
 
C

c

you have to rename "$Dir/$filename" to "$Dir/$filename.sql".
or do a chdir($Dir) before.

also, note that rename will always return "false" on most win9x systems even though the rename
happens properly - take out the 'or warn' portion and read in the new name to an 'if statement' to
see if it worked

related to this: rename won't do a directory, so how does one rename a directory in Perl without
doing a system call?? - I'm currently calling DOS to do it and hate that :)
 
T

Tassilo v. Parseval

Also sprach Purl Gurl:
For this case example, DOS performs with superiority over Perl.
When an "error" condition is generated, DOS will print a message
in Plain English, informing you of what happened. A true value
of zero is returned because the process was successful. An error
level greater than zero is generated when a process itself fails.

And in which way is that any different to other operating systems?
Traditionally, UNIX commands return 0 on success on something else on
error. Same is usually the case for libc functions.

Perl just turns it around so that success can be treated as a true value
(exception is system() where the raw return value of the command is
returned). In case of errors, the error message is in $! (for real
system-calls). Note that $! contains the numerical error code when used
in numerical context.

There is also %! when using the Errno module which gives convenient
access to the error codes of your libc. This is also true for Windows.
I have no doubt this confuses the heck out of unix purists.

No, not at all. What actually surprises me is that you think that
UNIX does it any differently from Windows.

Tassilo
 
J

Jay Tilton

(e-mail address removed) wrote:

: also, note that rename will always return "false" on most win9x
: systems even though the rename happens properly

Which systems specifically?

Is this limitation documented somewhere? It sounds like the kind of
show-stopper that would be mentioned in perlport or perlwin32, but I
don't see anything pertinent.

: - take out the 'or
: warn' portion and read in the new name to an 'if statement' to see if
: it worked

Do you mean something like,

rename( $oldname, $newname );
warn "rename failed" unless -e $newname;

Blecch. Personally, I'd rather accept that the code I write won't run
on "most" Win9X systems than jump through that hoop all the time.

: related to this: rename won't do a directory, so how does one rename a
: directory in Perl without doing a system call??

Not seeing it happen. rename() seems to work fine on Win32
directories.

mkdir 'foo' or die "Cannot create directory: $!";
rename('foo', 'bar') or die "rename failed: $!\n";
if( -d 'bar' ) {
print "Yup! Directory 'bar' is there.\n";
} else {
print "Hrm. Directory 'bar' should exist, but does not.\n";
}

Can you share some details about the system that exhibits the
misbehaviors you describe? Are you using a decrepit version of Perl?

In future, please be aware of the line lengths in your articles.
Something around seventy columns is preferred by readers.
 
J

Jay Tilton

: Jay Tilton wrote:
: > c wrote:
: > : related to this: rename won't do a directory, so how does one rename a
: > : directory in Perl without doing a system call??
:
: > Not seeing it happen. rename() seems to work fine on Win32
: > directories.
:
: > mkdir 'foo' or die "Cannot create directory: $!";
: > rename('foo', 'bar') or die "rename failed: $!\n";
: > if( -d 'bar' ) {
: > print "Yup! Directory 'bar' is there.\n";
: > } else {
: > print "Hrm. Directory 'bar' should exist, but does not.\n";
: > }
:
:
: Research, read and learn about DOS "move" command for _renaming_
: directories, not _creating_ and renaming directories.

The purpose of the program was to challenge the statement that Perl's
rename() does not work on directories under Win32. The only purpose
of the "mkdir 'foo'" statement was to have a throwaway directory with
a known name available.

: #!perl
:
: open (FILE, ">foo") or die;
: close (FILE);
:
: mkdir 'foo' or die "Cannot create directory: $!";
: rename('foo', 'bar') or die "rename failed: $!\n";
: if( -d 'bar' )
: { print "Yup! Directory 'bar' is there.\n"; }
: else
: { print "Hrm. Directory 'bar' should exist, but does not.\n"; }
:
:
: PRINTED RESULTS:
: ________________
:
: Cannot create directory: File exists at test.pl line 6.

I assumed all readers would be able to change 'foo' to something else
as necessary to avoid colliding with existing filenames.

my( $old, $new ) = ('foo', 'bar');
for( $old, $new ) {
$_ = join '', map chr rand(26)+65, 1..8 while -e $_;
}
mkdir $old or die "Cannot create directory '$old': $!";
rename( $old, $new ) or die "rename failed: $!\n";
if( -d $new ) {
print "Yup! Directory '$new' is there.\n";
} else {
print "Hrm. Directory '$new' should exist, but does not.\n";
}
 
B

Bob Walton

related to this: rename won't do a directory, so how does one rename a directory in Perl without
doing a system call?? - I'm currently calling DOS to do it and hate that :)


Hmmmmm...I note that Perl's rename() will rename directories just fine
on my system: Win98SE, AS Perl build 806. What OS and Perl version
does it not work with?
 
C

c

On 28 Aug 2003 10:23:49 -0700, (e-mail address removed) (deepak p) wrote:

apologies about the rename of directories

I was handing in a relative path and didn't
notice that it still contained "e:\dir" rather than "e:\\dir"

sorry for the confusion
 
M

Matt Garrish

Purl Gurl said:
Read my code example beneath my signature. Will unix generated such
a user friendly message? Unix error messages are unreliable with
their varying from machine to machine and being user configurable.

DOS: File not found - false.txt

Your density is amazing. Thinking about what you are doing always helps
before posting:

print "Perl: ";
rename ("false.txt", "true.txt") or print "$!";
print "\n\n";
print "DOS: ";
`ren false.txt true.txt`;

Don't blame your own ignorance on Perl.

Matt
 
T

Tassilo v. Parseval

Also sprach Purl Gurl:
(snipped, attributes stripped by others)



Research, read and learn:

http://www.aplawrence.com/Unixart/errors.html

This article is nonsense. It's not in the responsibility of the
operating-system what a programmer does with its error-codes. See below.
No, Perl turns a system true value into a system failure value.
We view the Perl system failure value as a true value, knowing
of this inconsistent behavior written into perl core.

So you'd rather want 0 to be true and values greater or smaller than 0 to
be false?

Perl has exactly one inconsistency in regards to error-codes: It's
system(). However, there's a reason for it (namely to let users inspect
further what went wrong and therefore wont modify its return value).
Read my code example beneath my signature. Will unix generated such
a user friendly message? Unix error messages are unreliable with
their varying from machine to machine and being user configurable.

So watch this:

ethan@ethan:~$ cat ren.c
#include <stdio.h>
#include <string.h>
#include <errno.h>

int main (int argc, char **argv) {
if (argc < 3) {
fprintf(stderr, "Usage: %s file1 file2\n", argv[0]);
return 1;
}
if (rename(argv[1], argv[2]) != 0) {
fprintf(stderr, "%s: %s\n", strerror(errno), argv[1]);
return 1;
}
return 0;
}
ethan@ethan:~$ gcc -o ren ren.c
ethan@ethan:~$ ./ren
Usage: ./ren file1 file2
ethan@ethan:~$ ./ren not_there not_there1
No such file or directory: not_there
ethan@ethan:~$ mv not_there not_there1
mv: cannot stat `not_there': No such file or directory
ethan@ethan:~$ perl -e 'print rename("not_there","not_there1")||$!,"\n"'
No such file or directory

As it can be seen, the stringified error returned by the operating
system is "No such file or directory" (admittedly, the error-string
which is produced by ren.c doesn't handle all cases since it assumes the
error to be ENOENT but this can be easily handled by a switch-statement
or so). This is, btw, the problem for any programmer: It's totally up to
him which error-messages he decides to spit out. However, he can always
ask the operating-system to give him a default which is guaranteed to be
the same for the same error-code.
DOS is reliable, never varies in error messages and will print
a user friendly Plain English message.

So does a UNIX system.
Many, if not most Perl users, when using a Unix system, rarely learn
Unix itself. Most cannot be bothered being only interested in Perl or
do not have shell access under Unix. For these people, a numerical
return of zero would be viewed as failure, when it is not. This would
certainly cause confusion, yes?

'perldoc -f system' explicitely explains what to do with system's
return-value. If people don't bother to read it, it's there problem, not
Perl's.
Unix, Linux, no error message can be trusted to be true nor to be
comprehensible because both systems do not use standardized error
messages created in Plain English. Unix, Linux, error messages can
be configured to return anything, including "Oh FUBAR!"

The error messages on operating systems that are attached to error-codes
are hardwired in the libc, just as they are under DOS.

Or would you care to tell me how I can configure mv(1) to print "Oh
FUBAR!" when an error occurs?
What error message is generated by Unix / Linux?

See above. Btw, UNIX is not necessarily Linux. Linux is an operating
system, UNIX is not. Nowadays, it's a term for a bunch of operating
systems that all behave pretty similarily. Incidentally, the above
C-snippet would very likely run unchanged on Solaris, BSD, HP-UX,
MacOSX etc. All those will probably return different error-messages,
just as DOS and OS2 will likely produce different output.

Tassilo
 
M

Matt Garrish

Purl Gurl said:
You have a rather novel approach to dismiss
well known factual material. Perhaps not all
that novel with this being typical thinking
of many regulars here.

Quite the novel approach to cite "factual" material when your own posts are
filled with egregious errors. I'm curious to know why you've once again
tried to turn the conversation onto one of your boring tangents? Oh yeah,
you're trying to dodge the fact that you got caught trying to pontificate on
something you don't understand again.

Matt
 
J

James Willmore

(snipped a lot, review thread if you are falling behind)



Strikes me this is what my series of articles precisely
exemplifies, least for those with average reading
comprehension skills. I do believe I stated exactly
what you have, in my own words.


Purl Gurl

Really? I couldn't tell - you were too busy trying to make a point I
did in one sentence and one example ;)

Try not picking fights and you may make your point - and even become
well liked ;)
 
C

c

I would be interested to learn how you obtained results with
your script failing at the open directory line.

actually, something is still going wrong here

I'm not able to concentrate as well as I'm accustomed to,
since I'm currently recovering from a second heart attack, but
if you know why this is happening I'd be grateful for the info

I never repeated the original test case where I was accidentally
handing some directories into a routine that renamed a large
number of files

I made a test to see what was happening

here's the original test that didn't work:
rename ("e:\Temp", "e:\temp");

I thought it was the single slash and never repeated that
test, but now find that this still doesn't work:
rename ("e:\\Temp", "e:\\temp");

I'll look at it more later
 
S

Steve D

Purl Gurl said:
This is absolutely untrue.

Actually, for Win98 I believe it *is* true.

On Win2K (most likely any NT kernel), it is, as you say, untrue. See
example below.
(Not sure about *absolutely* -- I've programmed too long to use that
adjective).

On Win2K, rename takes case into account, but mkdir (and most other
file actions) ignore case. This is *defined* behavior on Win2K so
there should be no surprises.

Having worked with many systems, I find it a toss-up whether names
(file, program variables, or any other names) should be case sensitive
or not. Personally, I find the typical C code, with names that only
differ in case for lots of variables, difficult to read unless the
case usage is very consistent (which is rarely true).

DOS chose to make file names case-insensitive and Win* has to be
consistent with that (the burden of backwards compatibility). It was
a reasonable compromise with Win2K to permit case sensitivity for file
name *display*, but case insensitivity for file actions.

In any case, rename *ought* to allow you to rename the display name,
and on Win2K it does. It even allows one to rename a file to its
exact (case sensitive) display name without complaint.

I don't have a Win98 or Win95 system for testing (that OS sucked a
myriad of ways, contrary to NT). Based on earlier examples in this
thread, I'd guess that at least some version of Win9x failed to permit
rename if all it did was change display case.

If that is true, the two-step rename *is* the right way to change
display *case*. It works identically on any Win* system (even if it
is overkill on Win2K).

The two-step rename could even be considered the "standard" way to do
renames when you are not sure what Win system you are working with
*and* expect some renames to simply be a change to the displayed case.

The "funky" issues with renaming a file when the target existes are
identical on UNIX and Win*. If the "target name" already exists as a
directory, then the source file will be "moved" into that directory
without changing the basename of the file.

Regards,
Steve

C:\x>mkdir ThisIsCaseSensitiveDisplay

C:\x>dir
Directory of C:\x

09/01/2003 04:11p <DIR> .
09/01/2003 04:11p <DIR> ..
09/01/2003 04:11p <DIR> ThisIsCaseSensitiveDisplay
0 File(s) 0 bytes
3 Dir(s) 70,927,593,472 bytes free

C:\x>rename ThisIsCaseSensitiveDisplay thisiscasesensitivedisplay

C:\x>dir
Directory of C:\x

09/01/2003 04:11p <DIR> .
09/01/2003 04:11p <DIR> ..
09/01/2003 04:11p <DIR> thisiscasesensitivedisplay
0 File(s) 0 bytes
3 Dir(s) 70,927,593,472 bytes free

C:\x>rename thisiscasesensitivedisplay ThisIsCaseSensitiveDisplay

C:\x>dir
Directory of C:\x

09/01/2003 04:11p <DIR> .
09/01/2003 04:11p <DIR> ..
09/01/2003 04:11p <DIR> ThisIsCaseSensitiveDisplay
0 File(s) 0 bytes
3 Dir(s) 70,927,593,472 bytes free

C:\x>mkdir ThisIsCaseSensitiveDisplay
A subdirectory or file ThisIsCaseSensitiveDisplay already exists.

C:\x>mkdir thisiscasesensitivedisplay
A subdirectory or file thisiscasesensitivedisplay already exists.

C:\x>dir
Directory of C:\x

09/01/2003 04:14p <DIR> .
09/01/2003 04:14p <DIR> ..
09/01/2003 04:11p <DIR> ThisIsCaseSensitiveDisplay
0 File(s) 0 bytes
3 Dir(s) 70,927,523,840 bytes free
 

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,995
Messages
2,570,236
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top