Perl golf: lowercasing all path names

A

A. Farber

Hi,

I need to lowercase all files and directories in the current
directory on Linux and have come up with the following script:

bolinux72:bin {74} cat lowercase.sh
#!/bin/sh

# Lowercase the files and sub-directores in the current directory
# BUGS: does not escape quotes, backslashes and dollars in path names
# Note: for Unix change -print0 to -print, -n0e to -ne, mv -v to mv

find . -depth -print0 | perl -n0e '
$old = $_;
s,([^/]+)$,\L$1,;
next if $old eq $_;
die qq{Can not move "$old" to "$_"\n} if -e;
print qq{mv -v "$old" "$_"\n}' | sh

And 1 line more for the same task, but with uppercased first letter:

bolinux72:bin {75} cat upfirst.sh
#!/bin/sh

# Uppercase the first letter and lowercase the rest for
# all files and sub-directores in the current directory

find . -depth -print0 | perl -n0e '
$old = $_;
s,([^/]+)$,\L$1,;
s,([^/]+)$,\u$1,;
next if $old eq $_;
die qq{Can not move "$old" to "$_"\n} if -e;
print qq{mv -v "$old" "$_"\n}' | sh

I wonder, if someone has a nicer solution and what
would be the best way to handle funny path names?

Regards
Alex
 
A

Anno Siegel

A. Farber said:
Hi,

I need to lowercase all files and directories in the current
directory on Linux and have come up with the following script:

That isn't what we call a golf problem, and advertising it a such
comes right next to announcing a "challenge" in your subject.

What you present is mostly not Perl at all, but a rendition of a shell
script with Perl used for string processing. Do it all in Perl and
we can talk.

IOW, use File::Find (or the newer File::Find::Rule, which I haven't
looked at) to gather the file names. Use Perl's rename() to do the
renaming (and check for success instead of making a guess with -e).
That way you won't have to worry about escaping weird path names
because no shell tries to interpret them. It won't make the
script shorter, but it will make it correcter.

Anno
bolinux72:bin {74} cat lowercase.sh
#!/bin/sh

# Lowercase the files and sub-directores in the current directory
# BUGS: does not escape quotes, backslashes and dollars in path names
# Note: for Unix change -print0 to -print, -n0e to -ne, mv -v to mv

find . -depth -print0 | perl -n0e '
$old = $_;
s,([^/]+)$,\L$1,;
next if $old eq $_;
die qq{Can not move "$old" to "$_"\n} if -e;
print qq{mv -v "$old" "$_"\n}' | sh

And 1 line more for the same task, but with uppercased first letter:

bolinux72:bin {75} cat upfirst.sh
#!/bin/sh

# Uppercase the first letter and lowercase the rest for
# all files and sub-directores in the current directory

find . -depth -print0 | perl -n0e '
$old = $_;
s,([^/]+)$,\L$1,;
s,([^/]+)$,\u$1,;
next if $old eq $_;
die qq{Can not move "$old" to "$_"\n} if -e;
print qq{mv -v "$old" "$_"\n}' | sh

I wonder, if someone has a nicer solution and what
would be the best way to handle funny path names?

Regards
Alex
 
A

Arndt Jonasson

That isn't what we call a golf problem, and advertising it a such
comes right next to announcing a "challenge" in your subject.

What is a golf problem?
 
J

Jürgen Exner

[What does your question have to do with Perl golf?]

A. Farber said:
I need to lowercase all files and directories in the current
directory on Linux and have come up with the following script:

bolinux72:bin {74} cat lowercase.sh
#!/bin/sh

# Lowercase the files and sub-directores in the current directory
# BUGS: does not escape quotes, backslashes and dollars in path names
# Note: for Unix change -print0 to -print, -n0e to -ne, mv -v to mv

find . -depth -print0 | perl -n0e '
$old = $_;
s,([^/]+)$,\L$1,;
next if $old eq $_;
die qq{Can not move "$old" to "$_"\n} if -e;
print qq{mv -v "$old" "$_"\n}' | sh

That's not Perl!

[...]
I wonder, if someone has a nicer solution and what

What about something along the line of (untested! just as a sketch of an
idea!):

use warnings; use strict;
use File::Find;
finddepth (\&wanted, '.');
sub wanted{
if (-e (lc)){
print "Target file name ". lc $_ . " in directory " .
$File::Find::dir . " already exists, can't rename $_\n";
} else {
rename $_, lc;
}
}
would be the best way to handle funny path names?

If we would just know what _you_ mean by "funny path names".

jue
 
A

A. Farber

IOW, use File::Find (or the newer File::Find::Rule, which I haven't
looked at) to gather the file names. Use Perl's rename() to do the
renaming (and check for success instead of making a guess with -e).
That way you won't have to worry about escaping weird path names
because no shell tries to interpret them. It won't make the
script shorter, but it will make it correcter.

Won't rename() call sh and thus be slower than just
printing a batch of mv-commands to one single sh?

BTW I've noticed that checking with -e in the perl part
won't work because of buffering and have to use "test -e"
(which makes it all uglier):

find . -depth -print0 | perl -n0e '
s,([`"\$\\]),\\$1,g;

$old = $_;
s,([^/]+)$,\L$1,;
next if $old eq $_;

print qq{
if test -e "$_"; then
echo "Can not move $old to $_: $_ exists already"
exit 1
else
mv -v "$old" "$_"
fi
}' | sh

I still think it's a legal perl problem. If someone has
a better solution with File::Find, I'd like to see it

Regards
Alex
 
J

Jürgen Exner

A. Farber said:
(e-mail address removed)-berlin.de (Anno Siegel) wrote in message

Won't rename() call sh and thus be slower than just

I haven't seen the implementation of rename() but why do believe it would
shell out?
That would be a very odd thing to do.
printing a batch of mv-commands to one single sh?

BTW I've noticed that checking with -e in the perl part
won't work because of buffering and have to use "test -e"

What buffering? rename() doesn't do any buffering.
(which makes it all uglier):

find . -depth -print0 | perl -n0e '
s,([`"\$\\]),\\$1,g;

$old = $_;
s,([^/]+)$,\L$1,;
next if $old eq $_;

print qq{
if test -e "$_"; then
echo "Can not move $old to $_: $_ exists
already" exit 1
else
mv -v "$old" "$_"
fi
}' | sh

Aaargggg!! What a concept! Using find(1) to call a perl script to create a
shell script to pipe to sh. I wonder if there is a more convoluted way.
I still think it's a legal perl problem.

Well, kind of. Strictly speaking it's more about getting your ducks in a row
then about a Perl problem. You could program this more elegantly in any
programming language.
If someone has
a better solution with File::Find, I'd like to see it

Guess you have missed my earlier post, then.

jue
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,269
Messages
2,571,100
Members
48,773
Latest member
Kaybee

Latest Threads

Top