Renaming file - Permission Denied

Discussion in 'Perl Misc' started by Bigus, Feb 10, 2009.

  1. Bigus

    Bigus Guest

    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
    -----------------
     
    Bigus, Feb 10, 2009
    #1
    1. Advertising

  2. Bigus

    Bigus Guest

    Thanks for the reply.

    "Ben Morrow" <> wrote in message
    news:...

    > 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:

    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
    -----------------
     
    Bigus, Feb 11, 2009
    #2
    1. Advertising

  3. Bigus

    szr Guest

    Ben Morrow wrote:
    > Quoth "Bigus" <>:
    >> "Ben Morrow" <> wrote in message
    >> news:...
    >>
    >> > 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:
    >>
    >>
    >>
    >> 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
     
    szr, Feb 11, 2009
    #3
  4. Bigus

    Bigus Guest

    "Ben Morrow" <> wrote in message
    news:...

    > 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
    -----------------
     
    Bigus, Feb 11, 2009
    #4
  5. Bigus

    szr Guest

    Bigus wrote:
    > "Ben Morrow" <> wrote in message
    > news:...
    >
    >> 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
     
    szr, Feb 11, 2009
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Chris
    Replies:
    1
    Views:
    850
    Roy Johnson
    Oct 28, 2003
  2. =?Utf-8?B?ZG90bmV0dGVzdGVy?=

    Renaming a Folder : access denied IIS 6.0/2003

    =?Utf-8?B?ZG90bmV0dGVzdGVy?=, Dec 6, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    2,054
    Patrick.O.Ige
    Dec 7, 2005
  3. Tina

    File access Permission Denied

    Tina, Mar 16, 2006, in forum: ASP .Net
    Replies:
    2
    Views:
    10,050
    Winista
    Mar 16, 2006
  4. Replies:
    4
    Views:
    5,879
  5. gmax2006
    Replies:
    3
    Views:
    17,204
    Damjan
    Aug 9, 2006
Loading...

Share This Page