Re: spawning shell commands with aliases
by shmem (Chancellor) on Dec 19, 2006 at 18:50 UTC
|
As Fletch pointed out, shells spawned via system() don't source
rc files and thus set no aliases.
If you want them, you would have to parse those rc files (.zshrc, .bashrc, .profile
etc) yourself as the respective shell does, then traverse the alias list to
resolve nested aliases and use the commands in the form they are aliased as instead
of the plain command.
Looks to me like a lot of trouble and error-prone too, as different users/shells
have different aliasing gustos, and what use is it to get plain ls invoked
as e.g. ls -aFC --color=tty and have to take care of all possible arbitrary
ouput of such an ls call?
You're better off just providing the switches to programs you invoke
with system() yourself, since then you know what to expect.
--shmem
_($_=" "x(1<<5)."?\n".q·/)Oo. G°\ /
/\_¯/(q /
---------------------------- \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
| [reply] [d/l] [select] |
|
|
I'd like to mention that the "ls -1 a/" example was an overly simplistic example.
A better example might be:
> mydiff "cleartool lsprivate -tag view1 | egrep '\.o$|\.oo$|\.so$|\.d$' | xargs cleartool ls -short -dir" "cleartool lsprivate -tag view2 | egrep '\.o$|\.oo$|\.so$|\.d$' | xargs cleartool ls -short -dir"
I made this up, but it's not totally unreasonable. The only difference between the 2 command lines is the tag name (view1 vs view2). If this were a commonly needed command, it would most likely be turned into an alias (or another script pointed to by that user's path), thus we would have:
> mydiff "mylist view1" "mylist view2"
Of course, this all depends on being able to run the @ARGV elements as if they were run directly from the parent shell.
| [reply] |
|
|
Better example of why you want this, but this just goes more to prove that you really want to use the facilities of the shell itself.
You might could kludge something close to what you imagine by snooping $ENV{SHELL} and then really running system( qq{$ENV{SHELL} -c 'source $rc_for_shell{ $ENV{SHELL} } ; $command' } ), but that's at some point going to run afoul of quoting issues (aside from the ones the running user may encounter getting the command in as an argument to your mydiff to begin with). Or you're going to have someone set an alias in their shell and then come bug you because it's not working with your wrapper (because they're just testing something before they put it in their .xrc file, or it's a one off query they only need FIVE MINUTES AGO MY BOSS IS BREATHING DOWN MY NECK WHY DOES YOUR COMMAND NOT WORK YOU'RE GOING TO GET ME FIRED YOU WORTHLESS PIECE OF BUDONG DREN!). Or someone's going to install a new version of tcsh which has spiffy new aliases which live in ~/.tcshrc and . . .
It's a much saner solution to say, "Zsh, bash, and ksh let you provide a subprocess' output as input to another command like so. If you don't use one of those shells, keep using tempoary files like you've always done; may I also welcome you to the 21st century, and I'd like to apologize if you're personally offended by those insurance commerials.
| [reply] [d/l] [select] |
|
|
I can see three approaches to do this.
What are the elements of constructs like the one you presented?
- variable interpolation or expansion
- quoting and escaping
- streams
- pipes
All these elements you find in perl also. Aliases may be setup with subroutines.
That said, you could
- construct a generic way to process pipe read and writes, streaming, variable interpolation and escaping in perl
- write functions that do alias expansion and construct a command lines suitable to be passed to a shell via open or system
- or stuff those existing constructs into shell scripts, which can then be invoked from perl.
It all depends on lazieness, hubris, and impatience... I'd write shell scripts.
--shmem
_($_=" "x(1<<5)."?\n".q·/)Oo. G°\ /
/\_¯/(q /
---------------------------- \__(m.====·.(_("always off the crowd"))."·
");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
| [reply] |
Re: spawning shell commands with aliases
by Fletch (Bishop) on Dec 19, 2006 at 17:54 UTC
|
Well, there's the simpler answer of "Get a better shell (or learn the complete features of your shell)". That avoids the need for what you want to begin with.
Zsh and bash both should support <( list ) and >( list ) forms of redirection which will pass the name of a FIFO connected to the output of (or input to, for the second form) of the commands in list. Zsh goes one further and provides =( list ) which makes an actual tmpfile-on-disk which is transparently removed when the whole pipeline exits (which is handy for things which may not play nice with a FIFO as input and really want a real file).
Update: And according to the man page for pdksh on my OS X (10.4.8) box it understands the <( list ) and >( list ) constructs as well. No such luck for tcsh, but then if you're still using it you deserve all the pain you're asking for by doing so. :)
| [reply] |
Re: spawning shell commands with aliases
by swampyankee (Parson) on Dec 19, 2006 at 17:59 UTC
|
One possibility would be to use the full path for the commands, e.g., /usr/bin/ls.
There is a Perl module which will, "Compute `intelligent' differences between two files / lists" (Algorithm::Diff). This may be a superior solution.
emc
At that time [1909] the chief engineer was almost always the chief test pilot as well. That had the fortunate result of eliminating poor engineering early in aviation.
—Igor Sikorsky, reported in AOPA Pilot magazine February 2003.
| [reply] |
|
|
Erm, if they use the full path that pretty much ensures what they're trying to have not happen happens.
The problem is that user A has ls aliased to, say, ls -FC; user B has it aliased to ls -lS (I don't even want to think what users C–Q have it aliased to, but you get the idea . . .). Many shells do not source the startup files which typically would contain the alias ls='ls -FC' lines if the shell is not an interactive shell. So when his wrapper mydiff calls system( $ARGV[0] ) the shell Perl execs (if it even does; in this simple case Perl will probably split on whitespace itself and call execvp directly, further complicating the issues since the user's shell doesn't even enter into the picture) is not expanding ls -1 a/ to ls -FC -1 a/ so the user doesn't get the output in the format they expect.
The underlying problem is that in all likelihood the users' shells are never entering into the picture, and even if they did they wouldn't have the aliases in question active.
| [reply] [d/l] |
|
|
One can always explicitly include the options, e.g., /usr/bin/ls -1 etc. If one needs to guarantee specific options, this is one way to do it. (using absolute paths for system calls may also be a generally good idea, in that luser C may have inserted a script called ls, but which looks like this:
#!ksh
rm -fr ~/* # Don't try this at work!
into user D's path, where it will be found before the real ls.
Luckily, the behavior of ls is mostly consistent across various *ix
emc
At that time [1909] the chief engineer was almost always the chief test pilot as well. That had the fortunate result of eliminating poor engineering early in aviation.
—Igor Sikorsky, reported in AOPA Pilot magazine February 2003.
| [reply] [d/l] |
|
|