Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Renaming file - Permission Denied

Reply
Thread Tools

Renaming file - Permission Denied

 
 
Bigus
Guest
Posts: n/a
 
      02-10-2009
Hi.

I have a script that recurses through a directory tree looking for OTF
fonts. When it finds one it extracts the postscript name and if the filename
is different then it attempts to rename the font file. However, it doesn't
rename the file and returns permission denied.

Strangely though, if I try the rename command stand-alone, ie: outside of
the loop where it runs through the files in the directory, it works. I'm
clutching at straws a bit here but is there some issue with renaming files
in a directory which is currently subject to the opendir command, or is it
something else entirely?

Here's the code:

----------------------------------------------

use strict;
use File::Copy;
use Font::TTF::Font;

recurser();

# -- recurse through 3 levels of folders -- #
sub recurser {

my $fromdir = "e:/software/fonts/";
my $fontext = "otf";

# level 1
opendir D1, $fromdir;
while( my $font1 = readdir(D1) ){
next if $font1 =~ /^\.+$/;
if(-d $fromdir.$font1){
# level 2
opendir D2, $fromdir.$font1;
while( my $font2 = readdir(D2) ){
next if $font2 =~ /^\.+$/;
# level 3
if(-d $fromdir.$font1.'/'.$font2){
opendir D3, $fromdir.$font1.'/'.$font2;
while( my $font3 = readdir(D3) ){
next if $font3 !~ /$fontext$/i;
renamefont
($fromdir.$font1.'/'.$font2.'/',$font3,$fontext);
}
closedir D3;
}
next if $font2 !~ /$fontext$/i;
renamefont ($fromdir.$font1.'/',$font2,$fontext);
}
closedir D2;
}
next if $font1 !~ /$fontext$/i;
renamefont ($fromdir,$font1,$fontext);
}
closedir D1;

}

# -- rename font -- ##

sub renamefont {

my($fontdir,$font,$ext) = @_;

my $f = Font::TTF::Font->open($fontdir.$font);
my $t = $f->{name}->read;
my $psname = $t->{strings}[6][1][0]{0};

if($psname =~ /\w+/ and $psname !~ /\s+/){
my $newfontname = $psname.'.'.$ext;
if($newfontname ne $font){
rename $fontdir.$font, $fontdir.$newfontname or
print 'rename '.$fontdir.$font.',
'.$fontdir.$newfontname.' failed<br>';
}
}

}

----------------------------------------------

As mentioned above if I just take the output from the failed rename command
in the above loop and run that on it's own, eg:

use strict;
rename "e:/software/fonts/M/MyriadPro-BlackSemiExt_____.otf",
"e:/software/fonts/M/MyriadPro-BlackSemiExt.otf";

it works.

Could someone tell me what's going wrong?

Thanks
Bigus



-----------------
www.Newsgroup-Binaries.com - *Completion*Retention*Speed*
Access your favorite newsgroups from home or on the road
-----------------
 
Reply With Quote
 
 
 
 
Bigus
Guest
Posts: n/a
 
      02-11-2009
Thanks for the reply.

"Ben Morrow" <> wrote in message
news:2mf966-...

> I'm going to take a wild guess and assume you're on Win32 .


Yes indeed

> You cannot
> rename a file while it's open on Win32, so you will need to get the
> Font::TTF::Font object to close the file before you do the rename. There
> is also sometimes an issue with virus scanners: if the scanner is set to
> scan-on-close, you can get the scanner re-opening the file immediately
> so you still can't rename it. If you can't kill your virus scanner try
> adding a sleep of a few seconds before the rename.


Nice idea. I had a look at the docs again for Font::TTF::Font and can't find
a close function but there is a "release" one which:

Quote:
Releases ALL of the memory used by the TTF font and all of its component
objects. After calling this method, do NOT expect to have anything left in
the Font::TTF::Font object
So the bit of the code that gets the postscript name is now:

my $f = Font::TTF::Font->open($fontdir.$font);
my $t = $f->{name}->read;
my $psname = $t->{strings}[6][1][0]{0};
$f->release();

It doesn't work though. I also disabled my virus scanner and put a sleep of
a couple of seconds just before the rename for good measure but it's still
failing to rename the font file

>> # level 1
>> opendir D1, $fromdir;

>
> You can use lexical dirhandles, as well.
>
> opendir my $D1, $fromdir or die "can't open '$fromdir': $!";
>
> Variables with numbers in the names are usually an indication you should
> be using an array instead.
>
> In any case, you should be using File::Find or File::Find::Rule or
> something instead of rolling your own.


Oh yes, thanks, that's a nifty module. Think I used that a few years ago but
had forgotten about it.

> <snippety>
>> next if $font3 !~ /$fontext$/i;

>
> This is incorrect. You mean /\.$fontext$/i, otherwise you will catch
> files called 'foo.gotf' and such like.


Aye, I realise that but I know there are only font files in the directories
I'm trawling through so didn't bother with the \.

Regards
Bigus


-----------------
www.Newsgroup-Binaries.com - *Completion*Retention*Speed*
Access your favorite newsgroups from home or on the road
-----------------
 
Reply With Quote
 
 
 
 
szr
Guest
Posts: n/a
 
      02-11-2009
Ben Morrow wrote:
> Quoth "Bigus" <>:
>> "Ben Morrow" <> wrote in message
>> news:2mf966-...
>>
>> > You cannot
>> > rename a file while it's open on Win32, so you will need to get the
>> > Font::TTF::Font object to close the file before you do the rename.
>> > There is also sometimes an issue with virus scanners: if the
>> > scanner is set to scan-on-close, you can get the scanner
>> > re-opening the file immediately so you still can't rename it. If
>> > you can't kill your virus scanner try adding a sleep of a few
>> > seconds before the rename.

>>
>> Nice idea. I had a look at the docs again for Font::TTF::Font and
>> can't find a close function but there is a "release" one which:
>>
>>
Quote:
>> Releases ALL of the memory used by the TTF font and all of its
>> component objects. After calling this method, do NOT expect to have
>> anything left in the Font::TTF::Font object
>>
>>
>> So the bit of the code that gets the postscript name is now:
>>
>> my $f = Font::TTF::Font->open($fontdir.$font);
>> my $t = $f->{name}->read;
>> my $psname = $t->{strings}[6][1][0]{0};
>> $f->release();
>>
>> It doesn't work though. I also disabled my virus scanner and put a
>> sleep of a couple of seconds just before the rename for good measure
>> but it's still failing to rename the font file

>
> Looking through the source (yuck, that's a fairly unpleasant module),
> it appears that ->release doesn't actually close the file. It look
> like allowing the object to go out of scope should do that, so you
> want something like
>
> my $psname;
> {
> my $f = Font::TTF::Font->open($fontdir.$font);
> my $t = $f->{name}->read;
> $psname = $t->{strings}[6][1][0]{0};
> $f->release;
> }
> rename ...;


One additional way would be to set the object to undef, which forces it
to destruct itself right then and there.

my $psname;
my $f = Font::TTF::Font->open($fontdir.$font);
my $t = $f->{name}->read;
$psname = $t->{strings}[6][1][0]{0};
$f->release;
$f = undef;

rename ...;

Although it I would agree the separate scope method seems more readable.

--
szr


 
Reply With Quote
 
Bigus
Guest
Posts: n/a
 
      02-11-2009
"Ben Morrow" <> wrote in message
news:hiq966-...

> my $psname;
> {
> my $f = Font::TTF::Font->open($fontdir.$font);
> my $t = $f->{name}->read;
> $psname = $t->{strings}[6][1][0]{0};
> $f->release;
> }
> rename ...;


That works

I also tried szr's suggestion of:

my $f = Font::TTF::Font->open($fontdir.$font);
my $t = $f->{name}->read;
my $psname = $t->{strings}[6][1][0]{0};
$f->release;
$f = undef;

but that didn't work. However, this did:

my $f = Font::TTF::Font->open($fontdir.$font);
my $t = $f->{name}->read;
my $psname = $t->{strings}[6][1][0]{0};
$f->release;
$t = undef;

So consequently I tried:

my $f = Font::TTF::Font->open($fontdir.$font);
my $t = $f->{name}->read;
my $psname = $t->{strings}[6][1][0]{0};
$t->release;

which also worked! Bit strange as the Font::TTF::Font clearly shows the
release() being applied to the open() handle.

Anyway, thank you very much for the help

Bigus


-----------------
www.Newsgroup-Binaries.com - *Completion*Retention*Speed*
Access your favorite newsgroups from home or on the road
-----------------
 
Reply With Quote
 
szr
Guest
Posts: n/a
 
      02-11-2009
Bigus wrote:
> "Ben Morrow" <> wrote in message
> news:hiq966-...
>
>> my $psname;
>> {
>> my $f = Font::TTF::Font->open($fontdir.$font);
>> my $t = $f->{name}->read;
>> $psname = $t->{strings}[6][1][0]{0};
>> $f->release;
>> }
>> rename ...;

>
> That works
>
> I also tried szr's suggestion of:
>
> my $f = Font::TTF::Font->open($fontdir.$font);
> my $t = $f->{name}->read;
> my $psname = $t->{strings}[6][1][0]{0};
> $f->release;
> $f = undef;
>
> but that didn't work. However, this did:
>
> my $f = Font::TTF::Font->open($fontdir.$font);
> my $t = $f->{name}->read;
> my $psname = $t->{strings}[6][1][0]{0};
> $f->release;
> $t = undef;
>
> So consequently I tried:
>
> my $f = Font::TTF::Font->open($fontdir.$font);
> my $t = $f->{name}->read;
> my $psname = $t->{strings}[6][1][0]{0};
> $t->release;
>
> which also worked! Bit strange as the Font::TTF::Font clearly shows
> the release() being applied to the open() handle.
>
> Anyway, thank you very much for the help


Ah, it would seem the file handle is associated with $t, not $f then.
Too bad it's documentation wasn't more clear about this.

--
szr


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
ImportError: libclntsh.so.10.1: cannot open shared object file: Permission denied gmax2006 Python 3 08-08-2006 11:27 PM
saving file permission denied on windows zombek@gmail.com Python 4 05-16-2006 01:59 PM
File access Permission Denied Tina ASP .Net 2 03-16-2006 06:07 PM
Renaming a Folder : access denied IIS 6.0/2003 =?Utf-8?B?ZG90bmV0dGVzdGVy?= ASP .Net 1 12-07-2005 02:45 AM
Can't do setuid and file permission denied Chris Perl 1 10-28-2003 03:34 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57