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

I want to rename all my file name to a path file name.
Example
The path to abc.txt =
c:\folder1\folder2\abc.txt
Since I'm using Windows, you can't rename file with "\" so I want to change it to "."
Output would be ".folder1.folder2.abc.txt" It wouldn't matter to me if drive name is there or not.
use File::Find; use File::Basename; use File::Spec; use strict; find ({ 'wanted' => \&renamefile }, 'c:\\folder1\\folder2'); sub renamefile { my $file = $_; return unless (-f $file); my $dirname = dirname($file); my $file_name = basename($file); my $new_file_name = $file_name; $new_file_name =~ s/\\\\/./g; rename($file,File::Spec->catfile($dirname,$new_file_name))or die; }
It is not renaming the file to the path file name

Replies are listed 'Best First'.
Re: rename file name in directory and subdir
by marinersk (Priest) on Aug 06, 2013 at 21:25 UTC
    Summary of Problem: You are converting the wrong data

    Desk checking your code, I suspected I understood the error. So I modified your code to show what you are actually asking the rename to do, and it was as expected: You are trying to rename the file to the same name it already has:

    use File::Find; use File::Basename; use File::Spec; use strict; find ({ 'wanted' => \&renamefile }, 'c:\\folder1\\folder2'); sub renamefile { my $file = $_; return unless (-f $file); my $dirname = dirname($file); my $file_name = basename($file); my $new_file_name = $file_name; $new_file_name =~ s/\\\\/./g; print "\$file = [$file]\n"; my $resulting_filename = File::Spec->catfile($dirname,$new_file_na +me); print "\$resulting_filename = [$resulting_filename]\n"; rename($file,File::Spec->catfile($dirname,$new_file_name))or die; } C:\Steve\Dev\PerlMonks\P-2013-08-06@1508-Rename-Fail>perl renameFailDe +bug.pl $file = [abc.txt] $resulting_filename = [abc.txt]

    Bottom line: You are supplying the unqualified filename and asking it to change all the backslashes (which by definition there are none) to dots.

    Since there are no backslashes in an unqualified filename, you get back the same name you supplied.

Re: rename file name in directory and subdir
by Cristoforo (Curate) on Aug 07, 2013 at 02:41 UTC
    In File::Find you are given three variables:
    $File::Find::dir is the current directory name,
    $_ is the current filename within that directory
    $File::Find::name is the complete pathname to the file.
    So, you don't need File::Basename to parse the file and directory. Unless your files are on a different drive, you could safely give the path without the drive letter, C:.

    marinersk pointed out the problem with your approach. A correct solution might be stated (below) using the 3 variables that come with File::Find.

    Also notice that perl can read forward slashes on a Windows machine - it's not necessary to have backslashes.

    This will rename all the files in folder1 and any subdirectories under it. (You might want to print out the proposed name changes before doing the operation to see that all is well.

    #!/usr/bin/perl use strict; use warnings; use File::Find; find(\&wanted, '/folder1'); sub wanted { if (-f) { (my $new = $File::Find::name) =~ s/\//./g; print "$File::Find::dir/$new\n"; #rename $File::Find::name, "$File::Find::dir/$new" # or warn "Can't rename $File::Find::name\n"; } }
      Nevermind, it works :)
Re: rename file name in directory and subdir
by mtmcc (Hermit) on Aug 06, 2013 at 20:29 UTC
    Is it for a specific directory?

    If so something like this might work, although I can't test it on windows at the moment:

    #!/usr/bin/perl use strict; use warnings; my $path = 'C:\folder1\folder2\'; my @newName = split (/\\/, $path); shift(@newName); my $rename = join(".", @newName); opendir (my $directory, $path) or die $!; while(readdir $directory) { next if $_ =~ m/^\./; my $fileName = "$rename" . ".$_"; rename $_, $fileName; }

      Beware, \' is special in single quotes.
      لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
        Thank you choroba, well spotted. Reason #121 not to use windows!! That would make it 'C:\folder1\folder2\\'. Is that right?

        EDIT:People who use perl on windows must be that bit sharper, having to account for file separators also escaping special characters in perl code.

      It not specific

      c:\folder1 has many files
      a.txt
      b.txt
      c.txt
      output
      .folder1.a.txt
      .folder2.b.txt
      .folder3.c.txt

      then c:\folder1\folder2 (in subdir)
      abc.txt
      cde.txt
      cfe.txt
      output
      .folder1.folder2.abc.txt
      .folder1.folder2.cde.txt
      .folder1.folder2.cfe.txt
      and so on....
        I rarely work with windows, and can't check this on windows, so you would have to switch the file separators in this. Also, I'm not certain that it's entirely safe to modify the @pathList array from the subroutine during the for loop. In any case this works for me, changing all the filenames in folders from the original path downwards:

        #! /usr/bin/perl use strict; use warnings; use diagnostics; my $originalPath = '/Path/To/file/'; my @pathList = ("$originalPath"); redoName($originalPath); for (@pathList) { redoName($_); } sub redoName { my $path = $_[0]; my @newName = split (/\//, $path); shift(@newName); my $newName = join(".", @newName); opendir (my $directory, $path) or die $!; while(readdir $directory) { my $fullName = "$path" . "$_"; unless (-d $fullName) { next if $_ =~ m/^\./; my $fileName = "$path" . "$newName" . ".$_";; rename $fullName, $fileName or die "couldn't r +ename: $!\n"; } if (-d "$fullName") { next if $_ =~ m/^\./; my $newPath = "$path" . "$_" . "\/"; push (@pathList, $newPath); } } }

Re: rename file name in directory and subdir
by starface245 (Novice) on Aug 07, 2013 at 15:15 UTC
    Thank you all for your help everyone and pointing out my mistake.. Thank you again.