For Programmers: Free Programming Magazines  


Home > Archive > PERL Miscellaneous > June 2005 > chown recursively









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author chown recursively
Tim O'Donovan

2005-06-09, 8:57 pm

Quick newbie question! Could someone please point out how to use chown()
on directories recursively.

But mostly I'd like to know if there are actually any benefits over using:

system("chown -R $uid:$gid $dir");


Thanks very much!

Tim
Lars Eighner

2005-06-09, 8:57 pm

In our last episode,
<d8a7r8$6u$1@nwrdmz01.dmz.ncs.ea.ibs-infra.bt.com>,
the lovely and talented Tim O'Donovan
broadcast on comp.lang.perl.misc:

> Quick newbie question! Could someone please point out how to use chown()
> on directories recursively.


> But mostly I'd like to know if there are actually any benefits over using:


> system("chown -R $uid:$gid $dir");


This is really a unix question, not a perl question. A word of
warning, though: beware of -R and .* -- it will recurse upward
because .. matches .* .

--
Lars Eighner eighner@io.com http://www.larseighner.com/
War on Terrorism: The Difference Between Us and Them
"We should invade their countries, kill their leaders and
convert them to Christianity." -- Ann Coulter
Tim O'Donovan

2005-06-09, 8:57 pm

Well my question was actually concerning whether using a Perl function
such as chown() had any benefits over using an equivalent system()
function to achieve the same the results.

Tim


Lars Eighner wrote:
> In our last episode,
> <d8a7r8$6u$1@nwrdmz01.dmz.ncs.ea.ibs-infra.bt.com>,
> the lovely and talented Tim O'Donovan
> broadcast on comp.lang.perl.misc:
>
>
>
>
>
>
>
>
> This is really a unix question, not a perl question. A word of
> warning, though: beware of -R and .* -- it will recurse upward
> because .. matches .* .
>

Christopher Nehren

2005-06-10, 3:59 am

On 2005-06-09, Tim O'Donovan scribbled these
curious markings:
> Quick newbie question! Could someone please point out how to use chown()
> on directories recursively.


Perhaps a bit of File::Find?

> But mostly I'd like to know if there are actually any benefits over using:
>
> system("chown -R $uid:$gid $dir");


Who says chown exists on the target system? Who says it's in your path?
It's generally a bad idea to "shell out" to external programs when you
can do what you need to do with Perl.

Best Regards,
Christopher Nehren
--
I abhor a system designed for the "user", if that word is a coded
pejorative meaning "stupid and unsophisticated". -- Ken Thompson
If you ask the wrong people questions, you get "Joel on Software".
Unix is user friendly. However, it isn't idiot friendly.
Kjetil Skotheim

2005-06-10, 3:59 am

On Fri, 10 Jun 2005 01:31:54 +0200, Christopher Nehren
<apeiron+usenet@coitusmentis.info> wrote:

> On 2005-06-09, Tim O'Donovan scribbled these
> curious markings:
>
> Perhaps a bit of File::Find?
>
>
> Who says chown exists on the target system? Who says it's in your path?
> It's generally a bad idea to "shell out" to external programs when you
> can do what you need to do with Perl.



I agree that GENERALLY this is a bad idea. But since chmod in itself
is very unix'ish, isn't it?, I think system should be permitted here.
....or if not permitted, I'd do a chmod to permit it...(uh)




>
> Best Regards,
> Christopher Nehren




--
Kjetil Skotheim
Tim Hammerquist

2005-06-10, 3:59 am

Tim O'Donovan <timodonovan@localhost.com> wrote:
> Quick newbie question! Could someone please point out how to use
> chown() on directories recursively.
>
> But mostly I'd like to know if there are actually any benefits over
> using:
>
> system("chown -R $uid:$gid $dir");


The chown() perl function is a direct interface to the system call.
There is significantly less overhead using this method, as opposed to
the one you describe above, which calls the OS to start a separate shell
session, then having the shell session open a process for the chown(1)
utility, which then makes a call to the same system function perl's own
chown() calls.

As mentioned elsewhere, chown() may not be available on some platforms.
Also heed the superuser note under chown() in perlfunc.

HTH,
another Tim
--
....the word "hack" is used as a verb to indicate
a massive amount of nerd-like effort.
-- Harley Hahn, "A Student's Guide to Unix"
Tim Hammerquist

2005-06-10, 3:59 am

Lars Eighner <eighner@io.com> wrote:
> This is really a unix question, not a perl question. A word of
> warning, though: beware of -R and .* -- it will recurse upward because
> .. matches .* .


# chown -R 000 .*

What? I don't see anything wronD?-^\^N???~D?????Rv^U??>^LP
%?~D#^][tf^???G?^@^G~G~O^Y~OD?^]?մ?V,?~E?U^WS+?|%0y?=/x7?]v?^WE?|?~Gu`[?ΩK~
%GpoQZ e??C?S^C4?GN?~E[?^Cb?aR?~@?=?^UQn??~T?^V?~K^D???^DM~_'?o??~Y^_?^V^L1
%^B^Y^V??~[3m?~WN ¢~T-?^K?\z?oln^M?~E4?ud?R|R?'3h~Pz?ĺ??
????/Zd???R?'~A?j9?
CARRIER LOST

Tim Hammerquist
--
$ echo espresso > /dev/coffee
Tad McClellan

2005-06-10, 3:59 am

Christopher Nehren <apeiron+usenet@coitusmentis.info> wrote:
> On 2005-06-09, Tim O'Donovan scribbled these curious markings:


[snip doing it in native Perl]


>
> Who says chown exists on the target system?



ie. portability between different machines.


> Who says it's in your path?



ie. portability between environments, even on *the same* machine.


> It's generally a bad idea to "shell out" to external programs when you
> can do what you need to do with Perl.



I tell students:

Doing it in native Perl will be safer, faster and more portable
than "shelling out".

Followed by some weasel wording about how that isn't an absolute,
but that it applies in the vast majority of cases.

Shelling out to Mathematica would very likely be preferrable to
getting the same thing done in native Perl for instance. :-)


--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas
Tim O'Donovan

2005-06-10, 3:59 am

Thanks for all your informative replies, much appreciated. From now on
I'll be replacing 'shell outs' with the appropriate Perl, where applicable.

So I can assume that using:

open(FIND, "find $path -lname '/home/$username/*' |");
@links = <FIND>;
close(FIND);

to find all the symbolic links in the given path to files in a users
home directory is also not the most resourceful method?!

I have some rethinking to do... :)


Thanks again,
Tim
Jürgen Exner

2005-06-10, 3:59 am

Tim O'Donovan wrote:
> Quick newbie question! Could someone please point out how to use
> chown() on directories recursively.


Sounds like a job for "use File::Find;".

> But mostly I'd like to know if there are actually any benefits over
> using:
> system("chown -R $uid:$gid $dir");


Of course, there are significant benefits. By using a Perl standard function
you are avoiding to fork an external process and to call an external program
that may or may not exist.
In short you are writing portable code.

jue


Jürgen Exner

2005-06-10, 3:59 am

Kjetil Skotheim wrote:
> On Fri, 10 Jun 2005 01:31:54 +0200, Christopher Nehren
>
>
> I agree that GENERALLY this is a bad idea. But since chmod in itself
> is very unix'ish, isn't it?, I think system should be permitted here.
> ...or if not permitted, I'd do a chmod to permit it...(uh)


Where do you find chown on a Windows PC, on a Mac, or a any of the dozen and
dozen OSs that are supported by Perl?

jue


Jürgen Exner

2005-06-10, 3:59 am

Tim O'Donovan wrote:
> open(FIND, "find $path -lname '/home/$username/*' |");
> @links = <FIND>;
> close(FIND);
>
> to find all the symbolic links in the given path to files in a users
> home directory is also not the most resourceful method?!


No, not exactly.
See "perldoc -f -l" for a better way.

jue


Tad McClellan

2005-06-10, 3:58 pm

Tim O'Donovan <timodonovan@localhost.com> wrote:

> From now on
> I'll be replacing 'shell outs' with the appropriate Perl, where applicable.


> open(FIND, "find $path -lname '/home/$username/*' |");



Pipe opens *are* "shelling out".


> to find all the symbolic links in the given path to files in a users
> home directory is also not the most resourceful method?!
>
> I have some rethinking to do... :)



And some reading:

perldoc File::Find

perldoc -f -X


--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas
Tim Hammerquist

2005-06-10, 3:58 pm

Jürgen Exner <jurgenex@hotmail.com> wrote:
> Where do you find chown on a Windows PC, on a Mac, or a any of the dozen and
> dozen OSs that are supported by Perl?


kotoko:~>% uname -a
Darwin kotoko 8.1.0 Darwin Kernel Version 8.1.0: Tue May 10 18:16:08
PDT 2005; root:xnu-792.1.5.obj~4/RELEASE_PPC Power Macintosh powerpc
kotoko:~>% which chown
/usr/sbin/chown

Of course, that's only Mac OS X (>= 10).

The point still stands. Native Perl functions should be used whenever
possible and appropriate to maintain portability.

For example, if you decide to shell out to an external chown(1) command,
it will work on Linux, *BSD, Solaris, and even Mac OS X, and several
others... but fail on Win32. Whereas if you used Perl's chown(), the
unimplemented function will return true and your script can continue as
normal.

Tim Hammerquist
--
With a PC, I always felt limited by the software available.
On Unix, I am limited only by my knowledge.
-- Peter J. Schoenster
Christopher Nehren

2005-06-10, 8:57 pm

On 2005-06-10, Tim Hammerquist scribbled these
curious markings:
> For example, if you decide to shell out to an external chown(1) command,
> it will work on Linux, *BSD, Solaris, and even Mac OS X, and several
> others...


.... though it may fail if you use syntax supported in your programming
environment's chown but not in your deployment environment's chown. For
example, GNU chown accepts '.' as a separator for user and group, which
is a violation of POSIX (though at least the documentation tells you
this). FreeBSD's chown follows POSIX and explicitly disallows this. All
the more reason to use Perl when possible.

Best Regards,
Christopher Nehren
--
I abhor a system designed for the "user", if that word is a coded
pejorative meaning "stupid and unsophisticated". -- Ken Thompson
If you ask the wrong people questions, you get "Joel on Software".
Unix is user friendly. However, it isn't idiot friendly.
Abigail

2005-06-10, 8:57 pm

Christopher Nehren (apeiron+usenet@coitusmentis.info) wrote on MMMMCCC
September MCMXCIII in <URL:news:slrndahkba.18m.apeiron+usenet@prophecy.dyndns.org>:
'' On 2005-06-09, Tim O'Donovan scribbled these
'' curious markings:
'' > Quick newbie question! Could someone please point out how to use chown()
'' > on directories recursively.
''
'' Perhaps a bit of File::Find?
''
'' > But mostly I'd like to know if there are actually any benefits over using:
'' >
'' > system("chown -R $uid:$gid $dir");
''
'' Who says chown exists on the target system? Who says it's in your path?
'' It's generally a bad idea to "shell out" to external programs when you
'' can do what you need to do with Perl.


It's generally a bad idea to label something as a "general bad idea".
Not every Perl program needs to be run on different platforms. I estimate
that in the more than 10 years I've been programming Perl, 98% of the
programs I've written were written to run a specific system.

If I were to write a program that needed to recursively chown a directory,
I'd use 'system' to do the task. Why roll your own if there's a canned
solution readily available? Code reuse goes much further than using a
Perl module. Oh, sure, there's no chown on Windows or MacOS, but doing a
chown() on those systems doesn't make much sense, does it? And if people
want to set up their paths such they lack access to 'chown', they have to
blame themselves. It's not my task to prevent people shooting themselves
in their feet.



Abigail
--
map{${+chr}=chr}map{$_=>$_^ord$"}$=+$]..3*$=/2;
print "$J$u$s$t $a$n$o$t$h$e$r $P$e$r$l $H$a$c$k$e$r\n";
Abigail

2005-06-10, 8:57 pm

Tim Hammerquist (tim@vegeta.ath.cx) wrote on MMMMCCCI September MCMXCIII
in <URL:news:slrndajg4c.mt.tim@vegeta.saiyix>:
$$ Jürgen Exner <jurgenex@hotmail.com> wrote:
$$ > Where do you find chown on a Windows PC, on a Mac, or a any of the dozen and
$$ > dozen OSs that are supported by Perl?
$$
$$ kotoko:~>% uname -a
$$ Darwin kotoko 8.1.0 Darwin Kernel Version 8.1.0: Tue May 10 18:16:08
$$ PDT 2005; root:xnu-792.1.5.obj~4/RELEASE_PPC Power Macintosh powerpc
$$ kotoko:~>% which chown
$$ /usr/sbin/chown
$$
$$ Of course, that's only Mac OS X (>= 10).
$$
$$ The point still stands. Native Perl functions should be used whenever
$$ possible and appropriate to maintain portability.
$$
$$ For example, if you decide to shell out to an external chown(1) command,
$$ it will work on Linux, *BSD, Solaris, and even Mac OS X, and several
$$ others... but fail on Win32. Whereas if you used Perl's chown(), the
$$ unimplemented function will return true and your script can continue as
$$ normal.


Yeah, but according to perlport, chown() isn't implemented on Plan 9.


Why would I care a script I write won't work on Windows? I bet the majority
of the Perl programs written aren't intended to run everywhere anyway.


Abigail
--
perl -wle 'print prototype sub "Just another Perl Hacker" {};'
Abigail

2005-06-10, 8:57 pm

Christopher Nehren (apeiron+usenet@coitusmentis.info) wrote on MMMMCCCI
September MCMXCIII in <URL:news:slrndajnmt.1a7a.apeiron+usenet@prophecy.dyndns.org>:
&& On 2005-06-10, Tim Hammerquist scribbled these
&& curious markings:
&& > For example, if you decide to shell out to an external chown(1) command,
&& > it will work on Linux, *BSD, Solaris, and even Mac OS X, and several
&& > others...
&&
&& ... though it may fail if you use syntax supported in your programming
&& environment's chown but not in your deployment environment's chown. For
&& example, GNU chown accepts '.' as a separator for user and group, which
&& is a violation of POSIX (though at least the documentation tells you
&& this). FreeBSD's chown follows POSIX and explicitly disallows this. All
&& the more reason to use Perl when possible.


Bullshit.

GNU chown also allows ':' as the separator. Which is the standard, and
which is what OP did as well.

Not using a tool because some implementations of the tool accept an
alternative method that isn't accepted on all implementation, while also
implementing the method that is accepted by all implementations isn't
a reason to not use a tool.


Abigail
--
perl -we 'print q{print q{print q{print q{print q{print q{print q{print q{print
qq{Just Another Perl Hacker\n}}}}}}}}}' |\
perl -w | perl -w | perl -w | perl -w | perl -w | perl -w | perl -w | perl -w
Abigail

2005-06-10, 8:57 pm

Tim Hammerquist (tim@vegeta.ath.cx) wrote on MMMMCCCI September MCMXCIII
in <URL:news:slrndahn7h.mt.tim@vegeta.saiyix>:
<> Tim O'Donovan <timodonovan@localhost.com> wrote:
<> > Quick newbie question! Could someone please point out how to use
<> > chown() on directories recursively.
<> >
<> > But mostly I'd like to know if there are actually any benefits over
<> > using:
<> >
<> > system("chown -R $uid:$gid $dir");
<>
<> The chown() perl function is a direct interface to the system call.
<> There is significantly less overhead using this method, as opposed to
<> the one you describe above, which calls the OS to start a separate shell
<> session, then having the shell session open a process for the chown(1)
<> utility, which then makes a call to the same system function perl's own
<> chown() calls.


Well, if the directory is large, I bet shelling out the chown is *faster*
than doing it in Perl. The system call doesn't handle the -R functionality,
and I bet the C-implementation of traversing a directory tree in chown is
faster than most, if not every, Perl solution using File::Find.

Of course, the strongest argument is: programmer time is more important
than CPU time. The time to program out

system "chown -R $uid:$gid $dir";

utterly dwarves the overhead of starting another process. (And note that
unless '$uid', '$gid' and '$dir' contain characters that are special to
shell, no shell will be started by perl - perl will call chown directly).



Abigail
--
perl -Mstrict='}); print "Just another Perl Hacker"; ({' -le1
Abigail

2005-06-10, 8:57 pm

Tim O'Donovan (timodonovan@localhost.com) wrote on MMMMCCCI September
MCMXCIII in <URL:news:d8asat$a59$1@nwrdmz01.dmz.ncs.ea.ibs-infra.bt.com>:
() Thanks for all your informative replies, much appreciated. From now on
() I'll be replacing 'shell outs' with the appropriate Perl, where applicable.
()
() So I can assume that using:
()
() open(FIND, "find $path -lname '/home/$username/*' |");
() @links = <FIND>;
() close(FIND);
()
() to find all the symbolic links in the given path to files in a users
() home directory is also not the most resourceful method?!


Indeed. I'd write that as:

@links = `find $path -lname '/home/$username/*'`;



Abigail
--
$_ = "\nrekcaH lreP rehtona tsuJ"; my $chop; $chop = sub {print chop; $chop};
$chop -> () -> () -> () -> () -> () -> () -> () -> () -> () -> () -> () -> ()
-> () -> () -> () -> () -> () -> () -> () -> () -> () -> () -> () -> () -> ()
Tim O'Donovan

2005-06-11, 3:57 am

> Well, if the directory is large, I bet shelling out the chown is *faster*
> than doing it in Perl. The system call doesn't handle the -R functionality,
> and I bet the C-implementation of traversing a directory tree in chown is
> faster than most, if not every, Perl solution using File::Find.
>
> Of course, the strongest argument is: programmer time is more important
> than CPU time. The time to program out
>
> system "chown -R $uid:$gid $dir";
>
> utterly dwarves the overhead of starting another process. (And note that
> unless '$uid', '$gid' and '$dir' contain characters that are special to
> shell, no shell will be started by perl - perl will call chown directly).



Thanks for the alternative angle, excellent stuff. I'm considering using
the original system() function now because of what you said about speed.
This is part of a background script on a webserving machine that takes
instructions from a file written to by a CGI script so the time each
request takes to execute is of the utmost importance as we want to keep
the user waiting for as little as possible for the result of the
request. I've yet to find a way to use the sleep() function to sleep for
less than a second (although I'm sure to find a module that will do
this), so even though using the system() function might only reduce the
time by a millisecond, this could cause the CGI script to sleep for a
second more than it really needs to. Well, just under a second than it
*needs* to but...


> unless '$uid', '$gid' and '$dir' contain characters that are special to shell...


This is also good to know as it will only ever be passed variables from
the calling CGI script like so:

system("chown -R 1100:80 /home/username/public_html");

The $uid value is taken directly from a passwd file, $gid is a constant
of 80 and if $username is not alphanumeric the CGI script will return an
error.



Tim
Tim O'Donovan

2005-06-11, 3:57 am

Abigail wrote:
> Indeed. I'd write that as:
>
> @links = `find $path -lname '/home/$username/*'`;


I have been getting rather trying to find a way to achieve this
using the -l file test as a few people have suggested. From the perldoc
it describes this as finding the symbolic links to a file that *don't*
resolve; I need to find links that *do*. I will probably now use your
suggestion to achieve this due to my frivolous attempts at using !-l !


Tim
Brian McCauley

2005-06-11, 8:56 am

Abigail wrote:

> Of course, the strongest argument is: programmer time is more important
> than CPU time. The time to program out
>
> system "chown -R $uid:$gid $dir";
>
> utterly dwarves the overhead of starting another process. (And note that
> unless '$uid', '$gid' and '$dir' contain characters that are special to
> shell, no shell will be started by perl - perl will call chown directly).


But even the briefest consideration of the question of whether or not
$dir may contain shell meta character takes more programmer time than
typing the extra punctuation to avoid this being an issue.

system 'chown','-R',"$uid:$gid",$dir;

Brian Wakem

2005-06-11, 8:56 am

Tim O'Donovan wrote:

> I've yet to find a way to use the sleep() function to sleep for
> less than a second
>
> Tim



use Time::HiRes qw(sleep);

sleep(0.2);



--
Brian Wakem


Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com