http://qs1969.pair.com?node_id=462384

jon12 has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to get some clarity on Perl's ability to rename non-ascii files. I would like to rename only non-ascii files in a directory that contains ascii and non-ascii filenames.

However, I am finding that with the standard Perl rename(oldfilename, newfilename) I recieve a "Permission Denied at <STDIN> line xxx" where xxx is the line containing the rename command. This error only appears when Perl attempts to rename a non-ascii filename.

Using the bactick rename: `rename \"oldfilename\" \"newfilename\"` the program seems to work with the caveat that Perl sees the non-ascii filenames as question marks ????? ????? and seems to find multiple duplicates and cannot rename all found. Error: Duplicate filename or file cannot be found.

Here is my code, I have many versions but this is my latest:

my $count = 1; print "Path to directory for renaming:\n"; chomp($dirname = <STDIN>); chdir $dirname or die "Cannot change to $dirname"; opendir(DIR, $dirname) or die "Cannot open $dirname"; while($myfile = readdir(DIR)) { $locate = telldir(DIR); if($myfile !~ m/[\?]+/gi) { print "$myfile: File is ascii\n"; } elsif($myfile =~ m/[\? ]+(\([0-9]+\))?\.(\w+)\i) #catches filenames + ???.txt or ????(2).txt { $count++; print "$myfile: File is non-ascii\n"; $ext = $2; $temp = "Non-Ascii_Filename_$count"; $newname = join "." $temp, $ext; rename($myfile, $newname) or warn $!; #rename \"$myfile\" \"$newname\"; #attempt with backtics } seekdir(DIR, $locate); } closedir(DIR);
Build: Active Perl v5.8.4
System: Windows XP Pro
Is there a better way to achieve the renaming of files, as neither of these methods are effective?
Thanks in advance.
john

Replies are listed 'Best First'.
Re: Renaming non-ascii files
by halley (Prior) on Jun 01, 2005 at 13:10 UTC

    One, you could be more clear that you're talking about non-ASCII filenames and not the contents. Someone above already seems confused on that point.

    Two, the "backticks rename" method relies on your operating system shell. On DOS/Windows, the rename command allows wildcards in source and target, and the shell has weak support for non-ASCII filenames. The graphical shell probably has a completely different set of bugs when dealing with non-ASCII filenames.

    Three, the internal rename() function relies on your operating system routines.

    Four, whenever you say "non-ASCII" you should indicate what encoding you are using. ISO-2022-JP? Codepage 328? What types of characters are you trying to put into filenames?

    Five, once you know the encoding you think you're using, look up the Encode modules and google around to see if anyone else has any similar problems or solutions.

    The quality of the help is always proportional to the quality of the question. Said another way, if we can't understand you, we can't offer the advice you seek.

    --
    [ e d @ h a l l e y . c c ]

Re: Renaming non-ascii files
by davidj (Priest) on Jun 01, 2005 at 11:41 UTC
    First of all, your code doesn't even compile. There are two errors:
    elsif($myfile =~ m/[\? ]+(\([0-9]+\))?\.(\w+)\i)
    needs to be changed to
    elsif($myfile =~ m/[\? ]+(\([0-9]+\))?\.(\w+)/i)
    and
    $newname = join "." $temp, $ext;
    needs to be changed to
    $newname = join ".", $temp, $ext;
    At that point it will compile. Please post the code you are actually using.
    davidj
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Renaming non-ascii files
by SolidState (Scribe) on Jun 01, 2005 at 14:04 UTC

    Hi Jon12,
    First of all, don't flame people that try to help you, or no one will want to help you. You got good advice about typos in your posted code. If the code you post is incorrect, it makes it harder for other people to help.

    With that out of the way, I have to say I don't understand exactly the problems you are experiencing. Sometimes you refer to non-ascii files (contents are not ascii?) and sometimes to non-ascii filenames. So which is it?
    I assume it is the filename, because that is what you seem to handle in your code. I'm not sure how to help, so I tried to simplify the code (so that it is easier to debug):

    use strict; use warnings; my $count = 1; print "Path to directory for renaming:\n"; chomp(my $dirname = <STDIN>); chdir $dirname or die "Cannot change to $dirname"; opendir(DIR, $dirname) or die "Cannot open $dirname"; for my $myfile (grep {m/[^[:ascii:]]/} readdir(DIR)) { print "$myfile: Filename is non-ascii\n"; rename($myfile, "Non-Ascii_Filename_$count.txt") or warn $!; $count++; } closedir(DIR);

    If this doesn't work, I'd like to hear how does a simple Perl "rename" of an ascii filename in the same directory and with the same permissions work.

    If a simple ascii filename can be renamed without a problem, try doing "print for (readdir(DIR));" instead of the entire "for" loop in the above program. Look at how Perl treats the non-ascii filenames.

    Other then that, I can only recommend trying out the File::Rename module from CPAN, psossibly it offers a more robust solution.

    Good luck :)

      I see where you are going, but it will not work.

      The reason I did not use:

      m/[^:ascii:]]/
      is Perl does not see the non-ascii characters at all. It sees only question marks for filenames. Even though in Windows the filenames appear in a native lanuage like Japanese or Arabic. Example: ??? ?? ???.txt is what Perl sees as a non-ascii filename. Therefore, I picked up non-ascii files using:
      m/[\?]+/
      and it worked...sometimes. The reason it does not work all the time is that if a file has exactly the same number of question marks perl considers it a duplicate and will not rename it.

      I need a method to make Perl, when reading a directory or globbing(i've tried globbing many of times, no go) to see these filenames as they are, not as question marks.

      thank for your assistance

Re: Renaming non-ascii files
by kaif (Friar) on Jun 01, 2005 at 17:21 UTC
    This does not address your problem directly, but I thought you might find this comment helpful.

    If, instead of renaming your files to "Non-Ascii_Filename_*" you would like to rename them to something similar to the non-ASCII filename (i.e. "Rós" to "Ros"), you might like to consider Text:Unidecode. The Perl Advent Calendar has a nice write-up.

Re: Renaming non-ascii files
by thcsoft (Monk) on Jun 01, 2005 at 11:39 UTC
    hmm... i'm a linux user. but aren't those unary operators like -f, -e, -b, and so on for windows as well?

    language is a virus from outer space.
      Yea, the -X operators work on all supported OSes. Though, I'm not sure if I've tested it on an Amiga... :)