Common file operations

  • Thread starter Shmuel (Seymour J.) Metz
  • Start date
S

Shmuel (Seymour J.) Metz

I'm trying to find Perl equivalents for some common operations in
other languages. I'm also looking for some style guides.

1. If I have a partial file name, how do I get the complete path?
I tried canon and glob, but both returned the partial name.

2. If I have a directory name and a file specification, ho do I find
all files in that directory matching the specification. File::Find
and issuing an ls command seem like overkill. I could use readdir
if I don't need a recursive search, but I was hoping for an
equivalent of SysFileTree in OS/2.

Any advice? Thanks.

--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>

Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to (e-mail address removed)
 
B

Ben Morrow

Quoth "Shmuel (Seymour J.) Metz said:
I'm trying to find Perl equivalents for some common operations in
other languages. I'm also looking for some style guides.

The canonical style guide is perlstyle... :)
1. If I have a partial file name, how do I get the complete path?
I tried canon and glob, but both returned the partial name.
File::Spec->rel2abs

2. If I have a directory name and a file specification, ho do I find
all files in that directory matching the specification.

From what you say below ITYM 'all files in that directory or any
subdir'? If you don't said:
File::Find and issuing an ls command seem like overkill. I could
use readdir if I don't need a recursive search, but I was hoping
for an equivalent of SysFileTree in OS/2.

File::Find or one of the modules built on it (e.g. File::Find::Rule) are
the only way (well, beyond rewriting File::Find yourself from readdir,
of course). Perl's interfaces are Unix-based; the only primitive for
reading directory entries in Unix is readdir.

OTOH if you don't care about portability you can probably find (or
fairly easily write: see perlxstut, perlxs; or Inline::C) an interface
to SysFileTree (that is, if you're actually working on OS/2 as opposed
to simply using it an an example).

Ben
 
M

Michele Dondi

1. If I have a partial file name, how do I get the complete path?
I tried canon and glob, but both returned the partial name.

I don't trust you! (Minimal) examples?

Also, see 'perldoc -q glob'.
2. If I have a directory name and a file specification, ho do I find
all files in that directory matching the specification. File::Find
and issuing an ls command seem like overkill. I could use readdir

Then just use File::Find. Ever heard about regexen?
if I don't need a recursive search, but I was hoping for an
equivalent of SysFileTree in OS/2.

Then glob() should do. Again, you should show some actual example
proving that it doesn't. See also

perldoc -f glob
perldoc File::Glob


Michele
 
J

Jürgen Exner

Shmuel said:
I'm trying to find Perl equivalents for some common operations in
other languages. I'm also looking for some style guides.

1. If I have a partial file name, how do I get the complete path?

Your question is not clear to me. Or maybe it is actually two questions?

First part would be to get the list of all filename, which match the given
partial name. Please note, typically this is not a 1:1 relationship but a
1:n because a given partial name can be completed into many actual names.
glob() will do that for you.

And the second part would be how to prepend the CWD to the file names found.
That's a trivial job for the double quote operator or the concatenation
operator ".".
I tried canon and glob, but both returned the partial name.

Where did you find a function "canon"? glob() is the right tool.
Please show us the actual code, then we may be able to find out why you
didn't get the results you expected.
2. If I have a directory name and a file specification, ho do I find
all files in that directory matching the specification.

What is a file specification in your terminlogoy?
File::Find
and issuing an ls command seem like overkill. I could use readdir
if I don't need a recursive search, but I was hoping for an
equivalent of SysFileTree in OS/2.

If you don't want to recurse into subdirectories then use readdir() (and
maybe stat() and other file information utilities to determine if each file
matches the specification).
If you want to recurse then use File::Find (and maybe stat() and other file
information utilities to determine if each file matches the specification).

jue
 
S

Shmuel (Seymour J.) Metz

on 10/26/2004 said:
I don't trust you! (Minimal) examples?

If you don't trust me, then what's the point of giving you examples?
Also, see 'perldoc -q glob'.

"No documentation found"
Then just use File::Find.

I will if what I wanted doesn't exist.
Ever heard about regexen?
No.

Then glob() should do.
No.

Again, you should show some actual example proving that it doesn't.

I might, for someone who isn't prejudiced. Why should I bother for
someone who already has made up her mind?
perldoc -f glob

No documentation found for "perlfunc"
perldoc File::Glob

I don't see anything there that wan't already in my de3ad tree.

--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>

Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to (e-mail address removed)
 
S

Shmuel (Seymour J.) Metz

on 10/25/2004 said:
Your question is not clear to me. Or maybe it is actually two
questions?

First, some background. In OS/2 there is no[1] concept of mounting a
directory; instead, file systems are referred to by drive letter,
there is a current dirve and each drive letter has an associated CWD.
A file specification of the form[2] d:\name.ext is interpreted as
d:\cwd\name.ext, a name of the form name.ext is interpreted as being
in the cwd of the current drive and a name of the form \path\name.ext
is interpreted as being in the specified directory on the current
drive. I'd like to allow the user to specify any of the forms and
convert them to d:\path\name.ext.
First part would be to get the list of all filename, which match the
given partial name. Please note, typically this is not a 1:1
relationship but a 1:n because a given partial name can be
completed into many actual names.

Of course.
And the second part would be how to prepend the CWD to the file
names found. That's a trivial job for the double quote operator or
the concatenation operator ".".

Simple but not trivial, because I have to first test whether the drive
is already their and whether the absolute path is already there.
Where did you find a function "canon"?

Sorry, that's a typo. It's the canonpath method of the File:Spec
module. It's in the online Perl documentation and also in the
Dromedary.
Where did you find a function "canon"? glob() is the right tool.

No, glob() expands wildcards but does not fill in implied components.
Please show us the actual code,

extproc G:\emx\bin\perl -STw
#!/usr/bin/perl -Tw
#
use constant TRUE => 1;
use constant FALSE => '';
use File::Spec qw(catdir catfile splitdir splitpath);
#ARGV=('m*','xyz');
my ($dir,$file)=@ARGV;
print '@ARGV=(',join(',',@ARGV),")\n";
print '$dir =',"$dir\n";
$dir =~ s/^\'?([^\']*)\'?$/$1/;
print '$dir =',"$dir\n";
print '$file=',"$file\n";
$file =~ s/^\'?([^\']*)\'?$/$1/;
print '$file=',"$file\n";
my @dirs=glob($dir);
print '@dirs=(',join(',',@dirs),")\n";
unless (scalar(@dirs) == 1) {
print "$dir matches multiple directory names:\n";
die ' ', join("\n ",@dirs),"\n"
}
die "$dir is an invalid directory name.\n" unless -d $dir;
What is a file specification in your terminlogoy?

I'd probably want to support the OS/2 conventions, which use * and ?
as wildcards, with ? matching a single component. I haven't decided
whether to restrict the input a bit or to translate into a regular
expression. d:\m?file.* would match, e.g., d:\cwd\mafile.cmd,
d:\cwd\mbfile.exe, d:\cwd\mcfile.html.
If you want to recurse then use File::Find (and maybe stat() and
other file information utilities to determine if each file matches
the specification).

That's what I wanted to avoid :-(

Thanks.

[1] Well, yes, but that doesn't count. And it leaves the same
underlying problem.

[2] OS/2 uses \ as a separator rather than /.

--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>

Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to (e-mail address removed)
 
S

Shmuel (Seymour J.) Metz

on 10/25/2004 said:
What computer language allows you to enter a partial file name and
get a complete path?
REXX.

Or do you mean you have a partial or relative path
representation and you want to get the full, absolute path name?
Yes.

If the latter, check out the File::Spec::Unix module or its brethren.

File::Spec::canonpath doesn't do it.
[answered elsewhere in this thread]

Not really. What was elsewhere in the thread was that I could write
code to do it, using File::Find, which I had said I'd like to avoid. I
was looking for an equivalent to

if file = '' then file = 'forward+*'
CALL SysFileTree file, files, FOS

which returns an array of file names, including drive and directory
information.

[1] Well, close enough.

--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>

Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to (e-mail address removed)
 
A

A. Sinan Unur

If you don't trust me, then what's the point of giving you examples?

He does not trust the assertions you make without providing test cases that
exhibit the problems you mention.
"No documentation found"

As it turns out, he was right not to trust you:

Found in C:\Perl\lib\pod\perlfaq5.pod
Is there a leak/bug in glob()?
Due to the current implementation on some operating systems, when you
use the glob() function or its angle-bracket alias in a scalar context,
you may cause a memory leak and/or unpredictable behavior. It's best
therefore to use glob() only in list context.

Why doesn't glob("*.*") get all the files?
Because even on non-Unix ports, Perl's glob function follows standard
Unix globbing semantics. You'll need "glob("*")" to get all (non-
hidden)
files. This makes glob() portable even to legacy systems. Your port may
include proprietary globbing functions as well. Check its documentation
for details.

You can also consult perldoc -f glob and perldoc perlop.
I will if what I wanted doesn't exist.

You haven't described what you want.

Then you shoud read

perldoc perlre
perldoc perlretut

etc so on and so forth.
I might, for someone who isn't prejudiced.

Feel free to insist on not asking questions _the_ smart way. I think all of
us are prejudiced against people who describe their problems in inexact
verbal form rather than in Perl (by the way, have you read the posting
guidelines for this group. They are posted here regularly).
Why should I bother for someone who already has made up her mind?

Are you related to Arnold Schwarzenegger by any chance? I would read the
name of the person I am corresponding with a little more carefully if I
were you.
No documentation found for "perlfunc"

Then you must have messed up your installation. Fix it soon. Programming
without documentation is not a good idea.
I don't see anything there that wan't already in my de3ad tree.

???

Sinan
 
T

Tad McClellan

Shmuel (Seymour J.) Metz said:
In <[email protected]>, on 10/26/2004
at 12:42 AM, Michele Dondi <[email protected]> said:


"No documentation found"


Then go find it!

(you have a broken perl installation)



You must live a sheltered life.



How do you know what glob() can and can't do if you cannot
access the docs for glob()?

Or do you just like typing "No" a lot?

I might, for someone who isn't prejudiced. Why should I bother for
someone who already has made up


Because there are hundreds of other people here besides the two of you,
and maybe one of them would help you if you helped them to help you...

her mind?


s/her/his/;
 
J

Jürgen Exner

Shmuel said:
on 10/25/2004 said:
Your question is not clear to me. Or maybe it is actually two
questions?

First, some background. In OS/2 there is no[1] concept of mounting a
directory; instead, file systems are referred to by drive letter,
there is a current dirve and each drive letter has an associated CWD.

[long and very reasonable explanation of special OS/2 requirements and
terminology snipped]

Sorry, that's beyond my expertise, never had any dealings with OS/2.

Maybe there is a module for dealing with the "current drive" and "CWD of the
current drive" and all that mess on CPAN already, but that's just a wild
guess.

jue
 
B

Ben Morrow

Quoth "Shmuel (Seymour J.) Metz said:
on 10/25/2004 said:
Your question is not clear to me. Or maybe it is actually two
questions?

First, some background. In OS/2 there is no[1] concept of mounting a
directory; instead, file systems are referred to by drive letter,
there is a current dirve and each drive letter has an associated CWD.
A file specification of the form[2] d:\name.ext is interpreted as
d:\cwd\name.ext, a name of the form name.ext is interpreted as being
in the cwd of the current drive and a name of the form \path\name.ext
is interpreted as being in the specified directory on the current
drive. I'd like to allow the user to specify any of the forms and
convert them to d:\path\name.ext.

I happen to know that the Win32 modules allow you to retreive te current
drive and current dir separately; I'd be pretty confident that either
the OS/2 modules do or that the Win32 modules will run under OS/2.

OTOH, File::Spec::Win32->rel2abs will do what you want, AFAICT.
Simple but not trivial, because I have to first test whether the drive
is already their and whether the absolute path is already there.

Which File::Spec does for you.
Sorry, that's a typo. It's the canonpath method of the File:Spec
module. It's in the online Perl documentation and also in the
Dromedary.

Yup; but canonpath is not the right function :). canonpath performs a
*logical* cleanup of the path: e.g. on Unix it remove /./ and /foo/../
sections, and double slashes; it performs equivalent cleanup on other
OSen, but never looks at the actual filesystem. As I said before, the
method you want is rel2abs, which will default to taking the path
relative to the cwd.
I'd probably want to support the OS/2 conventions, which use * and ?
as wildcards, with ? matching a single component. I haven't decided
whether to restrict the input a bit or to translate into a regular
expression. d:\m?file.* would match, e.g., d:\cwd\mafile.cmd,
d:\cwd\mbfile.exe, d:\cwd\mcfile.html.

In that case you want to use glob *after* rel2abs: rel2abs does not
check if the file exists, so it should correctly give you an absolute
glob pattern that will work. If that doesn't work, you could do

my @dirs = map { File::Spec->rel2abs($_) } glob $pattern;

You may also be interested in File::DosGlob, which may give you globbing
semantics you are more used to, I don't know.

Ben
 
S

Shmuel (Seymour J.) Metz

(2nd response)

on 10/25/2004 said:
What computer language allows you to enter a partial file name and
get a complete path?

REXX.

It turns out that Cwd::abs_path will do the job in Perl, although the
implimentation is ugly.

--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>

Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to (e-mail address removed)
 
M

Michele Dondi

Are you related to Arnold Schwarzenegger by any chance? I would read the
name of the person I am corresponding with a little more carefully if I
were you.

BTW: my (Italian, masculine) name, i.e. "Michele", is so often
mistaken in for the (French, feminine) "Michelle", that I'm by no
means bothered by this...


Michele
 
M

Michele Dondi

On Tue, 26 Oct 2004 19:37:05 -0300, "Shmuel (Seymour J.) Metz"

Unfortunately I can't help you with anything that is really OS/2
specific. Here are some hopefully constructive (i.e. that *you* will
hopefully judge to be constructive) cmts about your script in any
case:
extproc G:\emx\bin\perl -STw
#!/usr/bin/perl -Tw

BTW: do you really need -T? I suppose this is to be run from the
cmd/line and AFAICT doesnt' support risky operations, but I may be
wrong...

Also, with modern perls it's better to

use warnings;

instead. And

use strict;

*always*. (Well, but for one-liners, golfing, JAPHs, etc.)
use constant TRUE => 1;
use constant FALSE => '';

Huh?!? Don't do this! Well, if you really really like... then do it,
but in Perl it's not recommendable in any case. And certainly not
useful...
#ARGV=('m*','xyz');
my ($dir,$file)=@ARGV;

Hmmm, then I'd rather do (somthing like):

@ARGV == 2 or die "Usage: $0 said:
print '@ARGV=(',join(',',@ARGV),")\n";
print '$dir =',"$dir\n";

Not a real issue, but are you sure you want to print all these info?
In particular $dir and $file before and after the transformation...
$dir =~ s/^\'?([^\']*)\'?$/$1/;

Hey, and you said you had never heard about regexen...

However... you're just removing possible C<'>s from at ^ or $, right?
Then I suggest you do something like

s/^'//, s/'$// for $dir;

which is clearer IMHO...
print '$dir =',"$dir\n";
print '$file=',"$file\n";
$file =~ s/^\'?([^\']*)\'?$/$1/;

Oh, this one too, then why not doing them both in one run? A la

s/^'//, s/'$// for $dir, $name;

Also, still if you really *do* want to print all those info, then for
clarity resons you may consider an HERE doc instead.
print '$file=',"$file\n";
my @dirs=glob($dir);
print '@dirs=(',join(',',@dirs),")\n";
unless (scalar(@dirs) == 1) {
^^^^^^
^^^^^^

This is not required
print "$dir matches multiple directory names:\n";
die ' ', join("\n ",@dirs),"\n"
}
die "$dir is an invalid directory name.\n" unless -d $dir;

You may have used

@dirs=grep -d, glob $dir;

in the first place.
I'd probably want to support the OS/2 conventions, which use * and ?
as wildcards, with ? matching a single component. I haven't decided

This is the convention on *NIX and DOS/Win too. Apart that *NIX shells
support other ones as well.
[2] OS/2 uses \ as a separator rather than /.

Well, I don't know OS/2, and so I cannot tell about Perl under OS/2,
but under DOS/Windows the directory separator is \ too, however Perl
lets you use / anyway. I *guess* that it may be the same for OS/2.


Michele
 
S

Shmuel (Seymour J.) Metz

on 10/25/2004 said:
What computer language allows you to enter a partial file name and
get a complete path?
REXX.

Or do you mean you have a partial or relative path
representation and you want to get the full, absolute path name?
Yes.

If the latter, check out the File::Spec::Unix module or its brethren.

File::Spec::canonpath doesn't do it.
[answered elsewhere in this thread]

Not really. What was elsewhere in the thread was that I could write
code to do it, using File::Find, which I had said I'd like to avoid. I
was looking for an equivalent to

if file = '' then file = 'forward+*'
CALL SysFileTree file, files, FOS

which returns an array of file names, including drive and directory
information.

[1] Well, close enough.

--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>

Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to (e-mail address removed)
 
M

Michele Dondi

If you don't trust me, then what's the point of giving you examples?

Hmmm, maybe I should apologize... but I think you misunderstood the
sense of my cmt: it was intended ironic, sarcastic maybe, but
certainly not offensive. If, inadvertently, it was, then I apologize.

What I meant is that at all effects what you (not too clearly)
described seemed a good task for glob(). To be precise there's no
reason why it shouldn't work. If for any reason it didn't work for me,
then I'd suspect about me having done something wrong, however deeply
hidden the error may be, rather than blaming glob(). So I *could*
trust you, provided that you show me/us a possibly minimal example
exhibiting the allegedly wrong behaviour.
"No documentation found"

D'Oh! I'm sorry to inform you that your perl installation is broken...
I will if what I wanted doesn't exist.

Sorry, but I think that you didn't clearly say what it is that you
want. You named what I think to be an OS/2 system call, but I think
that most of us won't be that familiar with it anyway, so if only you
could express it also more verbosely...

Yes, you did!
WHY?!?


I might, for someone who isn't prejudiced. Why should I bother for
someone who already has made up her mind?

Side note: s/her/his/;

However the point was that, quite opposite to your assumption, I could
*not* make make up my mind because of lack of information. That
information are lacking... well, on this yes: I've made up my mind!
;-)
No documentation found for "perlfunc"

D'Oh! I'm sorry to inform you that your perl installation is broken...
I don't see anything there that wan't already in my de3ad tree.

Care to expand?


Michele
 
S

Shmuel (Seymour J.) Metz

on 10/27/2004 said:
He does not trust the assertions you make without providing test
cases that exhibit the problems you mention.

If he doesn't believe me, then why would he believe that the test
output came from my computer? He didn't simply say that she wanted to
see the test code and output, she called me a liar.
As it turns out, he was right not to trust you:

No. Nor were you.
Found in C:\Perl\lib\pod\perlfaq5.pod

Which doesn't alter the fact that I got the output I reported.
You can also consult perldoc -f glob and perldoc perlop.

I did, with the output I reported.
You haven't described what you want.

Yes I did.
Then you shoud read
perldoc perlre
perldoc perlretut

What would they tell me that isn't already available elsewhere, in
more convenient form? They certainly don't discuss anything called an
"regexen". Perhaps you should read more carefully.
Then you must have messed up your installation.

That is always a possibility.
Programming without documentation is not a good idea.

That's nice, but I wasn't doing that.

--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>

Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to (e-mail address removed)
 
S

Shmuel (Seymour J.) Metz

on 10/26/2004 said:
(you have a broken perl installation)

That's quite possible. I'll look into it, but I normally use
documentation in a different format.
You must live a sheltered life.

No. I just distinguish between "e" and "p" ;-)
How do you know what glob() can and can't do if you cannot access
the docs for glob()?

That question presupposes an assumption contrary to fact. I read the
documentation for glob prior to writing the test code.
Because there are hundreds of other people here besides the two of
you,

And, indeed, I posted the code in response to a different article.
s/her/his/;

Will do.

--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>

Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to (e-mail address removed)
 
S

Shmuel (Seymour J.) Metz

on 10/27/2004 said:
Please don't do this. Perl already has a well defined notion of true
and false. Don't invent new things.

I thought that it was clearer that way, but if it's considered to be
bad style then I won't do it.

Thanks.

--
Shmuel (Seymour J.) Metz, SysProg and JOAT <http://patriot.net/~shmuel>

Unsolicited bulk E-mail subject to legal action. I reserve the
right to publicly post or ridicule any abusive E-mail. Reply to
domain Patriot dot net user shmuel+news to contact me. Do not
reply to (e-mail address removed)
 

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,983
Messages
2,570,187
Members
46,747
Latest member
jojoBizaroo

Latest Threads

Top