After doing this:
> export PATH=/my/new/applications/path
instead of this:
> export PATH=/my/new/applications/path:$PATH
one too many times I decided to do something about it.
Enter Perl and a small about of shell scripting and I have an interactive way of toggling directories in my path (or any "path like" variable) on or off and adding directories to the beginning and end of my path.
The first part of this little utility is the setpath.pl script:
#!/usr/bin/perl
use strict;
my $variableName = shift;
if ( !$variableName ) {
$variableName = "PATH";
}
my $home = $ENV{HOME} || $ENV{LOGDIR} || (getpwuid($<))[7];
my $fName = "$home/.setpath.out";
if ( -e $fName ) {
unlink ( $fName )
or die( "Unable to unlink previous $fName file ($!)!\n" );
}
my @directories;
if ( !exists $ENV{$variableName} ) {
print( "No variable, $variableName, in the environment. Continue [Y/
+n]? " );
my $result;
do {
$result = <STDIN>;
chomp( $result );
if ( !defined($result) || lc($result) eq "n" ) {
exit( 1 );
}
} while ( lc($result) ne "y" && $result ne "" );
} else {
@directories = split( /:/, $ENV{$variableName} );
}
my $dirty = 0;
while( 1 ) {
print( "Your current $variableName contains:\n" );
for ( my $i = 0; $i < scalar(@directories); ++$i ) {
my $directory = $directories[ $i ];
my $state = "on";
if ( $directory =~ /\.off$/ ) {
$state = "off";
$directory =~ s/\.off$//;
}
printf( " %2d) [%3s] %s\n", $i, $state, $directory );
}
print(
'-----
Enter:
t<n> to toggle a directory on/off,
[a|A]<directory> to add a new directory (to front|end)
q to quit.
> ' );
my $commandLine = <STDIN>;
if ( !defined($commandLine) ) {
exit( 1 );
}
chomp( $commandLine );
$commandLine =~ /(.)(.*)/;
my ($command, $args) = ($1, $2);
if ( $command eq "t" ) {
if ( !defined($args) || $args eq "" ||
$args >= scalar(@directories) || $args < 0 ) {
print( "$args is not a valid directory number (0 .. ", scalar(@d
+irectories), ")\n\n" );
} else {
$dirty = 1;
if ( $directories[ $args ] =~ /\.off$/ ) {
$directories[ $args ] =~ s/\.off$//;
} else {
$directories[ $args ] .= ".off";
}
print( "\n" );
}
} elsif ( $command eq "A" ) {
push( @directories, $args );
$dirty = 1;
} elsif ( $command eq "a" ) {
splice( @directories, 0, 0, $args );
$dirty = 1;
} elsif ( $command eq "q" ) {
if ( $dirty ) {
open( OUT, "> $fName" )
or die( "Unable to open $fName for writing ($!)!\n" );
print OUT ("export $variableName=", join(":", @directories), "\n
+");
close( OUT );
exit 0;
} else {
print( "No changes made to $variableName.\n" );
exit( 1 );
}
}
}
Pretty much useless by itself as it doesn't actually change the path in any way. What it needs is a little bit of shell scripting to tie things together nicely. The following is for bash.
function setpath { /fully/qualified/path/to/setpath.pl "$1"; if [ $? =
+= 0 ]; then . $HOME/.setpath.out; echo "$1 updated."; fi };
Now I can safely play around with my PATH, LD_LIBRARY_PATH, etc... to my hearts content.
Re: Perl Path Editor for Unix
by graff (Chancellor) on Sep 14, 2005 at 04:58 UTC
|
I like this idea, but I think that having to face an interactive dialog with a perl script via STDIN every time I use it would give me a headache.
It wouldn't be that hard to adapt it so that @ARGV has all the information needed for just about every case -- e.g. consider a usage summary like this:
setpath.pl [ENV_VAR] [:NEWPATH | NEWPATH: | -[-]OLDPATH]
Default ENV_VAR is PATH
:NEWPATH appends ":NEWPATH" at end of ENV_VAR
NEWPATH: prepends "NEWPATH:" at start of ENV_VAR
-OLDPATH deletes first instance of "OLDPATH" from ENV_VAR
--OLDPATH deletes all instances of "OLDPATH" from ENV_VAR
Conceivably, you could handle multiple path args to be added or removed from the given variable in a single command line. For that matter, you could even do multiple variables on one command line:
setpath.pl VAR1 :NEWPATH VAR2 OTHERPATH: VAR3 --BADPATH
#
# shell function would be:
function setpath { /full/path/to/setpath.pl $*; if ... };
Maybe "chpath" would be a better name for the shell function.
update: Here is how I would do the @ARGV-based approach -- just a first attempt (I probably need to test more, esp. the regex for matching "valid" path args), but when combined with the appropriate shell function to use it, I think it would be serviceable for most needs. To me, it just seems a lot cleaner without all that prompting and reading user input on STDIN.
| [reply] [d/l] [select] |
|
my %path;
my ($high, $low) = (0,0);
for (split /:/, $ENV{PATH} ){
next if exists $path{$_}; # remove duplicates
$path{$_} = $high;
++$high;
}
for (@ARGV){
/^-(.*)/ and do {delete $path{$1} if exists $path{$1}; next;};
/^\+\+(.*)/ and do {--$low; $path{$1}=$low unless exists $path{$1};
+next;};
/^\+(.*)/ and do {++$high; $path{$1}=$high unless exists $path{$1};
+next;};
}
print join ":", sort {$path{$a} <=> $path{$b} } keys %path;
print "\n";
-- Murray Barton Do not seek to follow in the footsteps of the wise. Seek what they sought. -Basho
| [reply] [d/l] |
|
> export PATHTEST=/foo:/foobar:/foo/bar
> setpath.pl --/foo
> more .setpath.out
export PATHTEST=:bar:/bar/
>
This works if you append a ':' to the path you're removing (which I guess the script could do for you). It might be nice to add some sort of wild carding to the removals so you could remove every directory rooted at /foo.
I initially wrote mine to do removes but for my usage I prefer to temporarily toggle directories on/off. The tools developers I work with chose executable names that match those of a number of gnu tools I make use of so on occassion I need to temporaily remove one or other directory from my PATH. | [reply] |
Re: Perl Path Editor for Unix
by bluto (Curate) on Sep 13, 2005 at 21:23 UTC
|
FWIW, zsh's vared command ("vared PATH") is really nice for editing arbitrary env variables.
| [reply] |
Re: Perl Path Editor for Unix
by QM (Parson) on Sep 13, 2005 at 20:39 UTC
|
I had a similar problem on really old *nixes, where I had to suck in setups to run in various production environments. The old *nix couldn't take path variables over some limit, and would just chop it off, leaving only part of the necessary path, and a useless dangling root tip.
I had to save off the original path, suck in the new stuff, then cut out duplicates and other known useless bits, and set the path with the new shorter string. I think I just used a Perl script as a filter in backquotes in the shell, and all was (mostly) well...until I tried tcsh, but that's another story.
-QM
--
Quantum Mechanics: The dreams stuff is made of
| [reply] |
Re: Perl Path Editor for Unix
by duelafn (Parson) on Sep 15, 2005 at 16:00 UTC
|
This sort of thing is not too difficult to do in pure shell commands. Here's some code I picked up a while back after a quick google search. (original source)
Example Usage
add_path $HOME/bin
add_path $HOME/perl PERL5LIB
The functions
# @(#)Copyright (c) 1991 Simon J. Gerraty
#
# This file is provided in the hope that it will
# be of use. There is absolutely NO WARRANTY.
# Permission to copy, redistribute or otherwise
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
#
# Modified by Dean Serenevy (2005) for more robust quoting
# is $1 missing from $2 (or PATH) ?
no_path() { eval "case \":\$${2-PATH}:\" in *:\"$1\":*) return 1;; *)
+return 0;; esac"; }
# if $1 exists and is not in path, append it
add_path() { [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="\$${2:-P
+ATH}:$1"; }
# if $1 exists and is not in path, prepend it
pre_path() { [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="$1:\$${2
+:-PATH}"; }
# if $1 is in path, remove it
del_path() { no_path $* || eval ${2:-PATH}=`eval echo :'$'${2:-PATH}:
+| sed -e "s;:$1:;:;g" -e "s;^:;;" -e "s;:\$;;"`; }
| [reply] [d/l] [select] |
Re: Perl Path Editor for Unix
by scollyer (Sexton) on Sep 28, 2005 at 14:26 UTC
|
For those interested in a non-Perl-based approach to this problem, I have a set of bash/ksh functions
addpath
delpath
uniqpath
edpath
that allow you to manipulate path variables in various ways.
(which are idempotent addition of paths, deletion of paths based
on regex match, path uniquification, and path editing via your favourite editor)
They can be downloaded from
http://www.netspinner.co.uk/Downloads/pathfunc.tgz
They're in the public domain so you can do what you like
with them.
Steve Collyer
| [reply] |
|
http://www.netspinner.co.uk/Downloads/pathfunc.tgz
appears to be dead. Any idea where this code lives today?
| [reply] |
|
| [reply] |
|
|
|
|