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

I am attempting to get rid of all blank spaces in my filenames on my NT workstation and substitute them with underline character. Example:

file one name.doc
file-two name.doc
next file name.doc

I need them to all be this:

file_one_name.doc
file-two_name.doc
next_file_name.doc

My endless attempts are not working. Here is my latest attempt:
my $file = '.'; opendir(DIR,$file); @files=readdir(DIR); close(DIR); for(@files) { if($_ =~ m{/s+}) { s/$_/_/g } }

Replies are listed 'Best First'.
Re: Renaming files
by sch (Pilgrim) on Oct 25, 2002 at 16:26 UTC

    You've not included the actual rename in there (which I suspect you're aware of) but the code won't work because you're match should be m/\s+/g - the \s matches whitespace rather than the /s you have. Also the s///g is slightly incorrect. A basic outline might look something like:

    #!/usr/bin/perl my $file = '.'; opendir(DIR,$file); @files=readdir(DIR); close(DIR); for(@files) { if ( m/ /g) { my $oldfile = $_; s/ /_/g; rename $oldfile, $_; } print $_."\n"; }

    Of course, you need to consider what happens if you have a conflict such as what would happen if you had 2 files called 'test file' & 'test_file' - how would you handle this?

    Hey, if there's code up ^^ there ^^, don't blame me if it doesn't work.

    But today you took me walking, Through a land that we have lost,
    While our children sit at websites, With no access to the cost

      Of course, you need to consider what happens if you have a conflict such as what would happen if you had 2 files called 'test file' & 'test_file' - how would you handle this?
      If it were me, I would build a hash of arrays, the key of the hash being the new file name, and the array elements being all files that would have that new name. Here's a quicky:
      #!perl -w use strict; opendir(DIR,".") or die "Couldn't opendir on .: $!"; while($file = readdir(DIR)){ my $oldfile = $file; $file =~ s/\s+/_/g; push @{$hash{$file}}, $oldfile; } closedir(DIR) or warn "Couldn't close directory .: $!"; foreach my $key (keys %hash){ if(scalar(@{$hash{$key}}) != 1){ print "The following files would have been renamed to the same + thing:\n" local $"="\n"; print "@{$hash{$key}}", "\n"; } else{ print "$hash{$key}[0] -> $key " my $status = rename $hash{$key}[0], $key; if(!$status){ print "Failed\n"; } else{ print "Succeeded\n"; } } }

      thor

      Thank you!
Re: Renaming files
by fruiture (Curate) on Oct 25, 2002 at 16:21 UTC

    What you do in your code is getting names of files froma directory and then changing the in-memory strings, which has no effect on the actual file. Try this (untested):

    my $dir = '.'; require File::Spec; opendir my $dh,$dir or die "$dir - $!"; while(defined(my $f = readdir($dh))){ local $_ = File::Spec->catpath(undef,$dir,$f); next unless -f; $f =~ tr/ \t/_/s; my $np = File::Spec->catpath(undef,$dir,$f); rename $_ => $np or warn "rename '$_' to '$np': $!"; } closedir $dh;
    --
    http://fruiture.de
      Thanks, now can you explain these lines: What are these doing?
      require File::Spec; local $_ = File::Spec->catpath(undef,$dir,$f); my $np = File::Spec->catpath(undef,$dir,$f);

        See `perldoc -f require` and `perldoc File::Spec` for documentation.

        --
        http://fruiture.de
      Thanks, now can you explain these lines: What are these doing? require File::Spec; local $_ = File::Spec->catpath(undef,$dir,$f); my $np = File::Spec->catpath(undef,$dir,$f);