Vra

Dit is tipies om so iets in jou cshrc-lêer te hê om die pad te stel:

set path = ( . $otherpath $path )

maar die pad word gedupliseer wanneer jy jou cshrc-lêer verskeie kere bron kry, hoe voorkom jy die duplisering?

EDIT:Dit is een onrein manier om dit te doen:

set localpaths = ( . $otherpaths )
echo ${path} | egrep -i "$localpaths" >& /dev/null
if ($status != 0) then
    set path = ( . $otherpaths $path )
endif
Was dit nuttig?

Oplossing

Jy kan die volgende Perl script gebruik om paaie van duplikate snoei.


#!/usr/bin/perl
#
# ^^ ensure this is pointing to the correct location.
#
# Title:    SLimPath
# Author:   David "Shoe Lace" Pyke <eselle@users.sourceforge.net >
#   :   Tim Nelson 
# Purpose: To create a slim version of my envirnoment path so as to eliminate
#       duplicate entries and ensure that the "." path was last.
# Date Created: April 1st 1999
# Revision History:
#   01/04/99: initial tests.. didn't wok verywell at all
#       : retreived path throught '$ENV' call
#   07/04/99: After an email from Tim Nelson <wayland@ne.com.au> got it to
#         work.
#       : used 'push' to add to array
#       : used 'join' to create a delimited string from a list/array.
#   16/02/00: fixed cmd-line options to look/work better
#   25/02/00: made verbosity level-oriented
#
#

use Getopt::Std;

sub printlevel;

$initial_str = "";
$debug_mode = "";
$delim_chr = ":";
$opt_v = 1;

getopts("v:hd:l:e:s:");

OPTS: {
    $opt_h && do {
print "\n$0 [-v level] [-d level] [-l delim] ( -e varname | -s strname | -h )";
print "\nWhere:";
print "\n   -h  This help";
print "\n   -d  Debug level";
print "\n   -l  Delimiter (between path vars)";
print "\n   -e  Specify environment variable (NB: don't include \$ sign)";
print "\n   -s  String (ie. $0 -s \$PATH:/looser/bin/)";
print "\n   -v  Verbosity (0 = quiet, 1 = normal, 2 = verbose)";
print "\n";
        exit;
    };
    $opt_d && do {
        printlevel 1, "You selected debug level $opt_d\n";
        $debug_mode = $opt_d;
    };
    $opt_l && do {
        printlevel 1, "You are going to delimit the string with \"$opt_l\"\n";
        $delim_chr = $opt_l;
    };
    $opt_e && do {
        if($opt_s) { die "Cannot specify BOTH env var and string\n"; }
        printlevel 1, "Using Environment variable \"$opt_e\"\n";
        $initial_str = $ENV{$opt_e};
    };
    $opt_s && do {
        printlevel 1, "Using String \"$opt_s\"\n";
        $initial_str = $opt_s;
    };
}

if( ($#ARGV != 1) and !$opt_e and !$opt_s){
    die "Nothing to work with -- try $0 -h\n";
}

$what = shift @ARGV;
# Split path using the delimiter
@dirs = split(/$delim_chr/, $initial_str);

$dest;
@newpath = ();
LOOP: foreach (@dirs){
    # Ensure the directory exists and is a directory
    if(! -e ) { printlevel 1, "$_ does not exist\n"; next; }
    # If the directory is ., set $dot and go around again
    if($_ eq '.') { $dot = 1; next; }

#   if ($_ ne `realpath $_`){
#           printlevel 2, "$_ becomes ".`realpath $_`."\n";
#   }
    undef $dest;
    #$_=Stdlib::realpath($_,$dest);
    # Check for duplicates and dot path
    foreach $adir (@newpath) { if($_ eq $adir) { 
        printlevel 2, "Duplicate: $_\n";
        next LOOP; 
    }}

    push @newpath, $_;
}

# Join creates a string from a list/array delimited by the first expression
print join($delim_chr, @newpath) . ($dot ? $delim_chr.".\n" : "\n");

printlevel 1, "Thank you for using $0\n";
exit;

sub printlevel {
    my($level, $string) = @_;

    if($opt_v >= $level) {
        print STDERR $string;
    }
}

Ek hoop dis nuttig.

Ander wenke

Ek is verbaas dat niemand die gebruik het nie tr ":" "\n" | grep -x tegniek om te soek of 'n gegewe vouer reeds in $PATH bestaan.Enige rede om nie?

In 1 reël:

if ! $(echo "$PATH" | tr ":" "\n" | grep -qx "$dir") ; then PATH=$PATH:$dir ; fi

Hier is 'n funksie wat ek self gemaak het om verskeie dopgehou gelyktydig by $PATH te voeg (gebruik "aaa:bbb:ccc"-notasie as argument), en kyk elkeen vir duplikate voordat dit bygevoeg word:

append_path()
{
    local SAVED_IFS="$IFS"
    local dir
    IFS=:
    for dir in $1 ; do
        if ! $( echo "$PATH" | tr ":" "\n" | grep -qx "$dir" ) ; then
            PATH=$PATH:$dir
        fi
    done
    IFS="$SAVED_IFS"
}

Dit kan in 'n skrif soos volg genoem word:

append_path "/test:$HOME/bin:/example/my dir/space is not an issue"

Dit het die volgende voordele:

  • Geen bashisms of enige dop-spesifieke sintaksis nie.Dit loop perfek saam !#/bin/sh (ek getoets met streep)
  • Veelvuldige dopgehou kan gelyktydig bygevoeg word
  • Geen sortering nie, behou vouervolgorde
  • Hanteer perfek met spasies in vouername
  • 'n Enkele toets werk, maak nie saak of $folder by begin, einde, middel is of die enigste gids in $PATH is nie (dus vermy die toetsing van x:*, *:x, :x:, x, soos baie van die oplossings hier implisiet doen)
  • Werk (en bewaar) as $PATH met ":" begin of eindig, of "::" daarin het (wat beteken huidige vouer)
  • Geen awk of sed benodig word.
  • EPA vriendelik ;) Oorspronklike IFS waarde word bewaar, en alle ander veranderlikes is plaaslik tot die funksie omvang.

Hoop dit help!

ok, nie in csh, maar dit is hoe ek $ HOME / bin voeg vir my pad in bash ...

case $PATH in
    *:$HOME/bin | *:$HOME/bin:* ) ;;
    *) export PATH=$PATH:$HOME/bin
esac

geur na smaak ...

Ek het al met behulp van die volgende (Bourne / Korn / POSIX / Bash) script vir die grootste deel van 'n dekade:

:   "@(#)$Id: clnpath.sh,v 1.6 1999/06/08 23:34:07 jleffler Exp $"
#
#   Print minimal version of $PATH, possibly removing some items

case $# in
0)  chop=""; path=${PATH:?};;
1)  chop=""; path=$1;;
2)  chop=$2; path=$1;;
*)  echo "Usage: `basename $0 .sh` [$PATH [remove:list]]" >&2
    exit 1;;
esac

# Beware of the quotes in the assignment to chop!
echo "$path" |
${AWK:-awk} -F: '#
BEGIN   {   # Sort out which path components to omit
            chop="'"$chop"'";
            if (chop != "") nr = split(chop, remove); else nr = 0;
            for (i = 1; i <= nr; i++)
                omit[remove[i]] = 1;
        }
{
    for (i = 1; i <= NF; i++)
    {
        x=$i;
        if (x == "") x = ".";
        if (omit[x] == 0 && path[x]++ == 0)
        {
            output = output pad x;
            pad = ":";
        }
    }
    print output;
}'

In Korn dop, ek gebruik:

export PATH=$(clnpath /new/bin:/other/bin:$PATH /old/bin:/extra/bin)

Dit laat my met PATH met die nuwe en ander bin dopgehou aan die voorkant, plus een afskrif van elke naam gids in die hoof pad waarde, behalwe dat die ou en ekstra bin dopgehou bin verwyder.

Jy sal hê om hierdie te pas by C dop (jammer - maar ek is 'n groot gelowige in die waarhede uiteengesit by C Shell Programmering beskou Skadelik ). Hoofsaaklik, sal jy nie hoef te peuter met die kolon separator, so lewe is eintlik makliker.

Wel, as jy nie omgee wat bestel jou paaie is in, jy kan iets soos te doen:

set path=(`echo $path | tr ' ' '\n' | sort | uniq | tr '\n' ' '`)

Dit sal sorteer jou paaie en enige ekstra paaie wat dieselfde is verwyder. As jy het . in jou pad, kan jy dit verwyder met 'n grep-v en voeg dit weer aan die einde.

Hier is 'n lang een-liner sonder Sortering:
stel pad = (echo $path | tr ' ' '\n' | perl -e 'while (<>) { print $_ unless $s{$_}++; }' | tr '\n' ' ')

dr_peper,

Ek verkies gewoonlik om te hou by script vermoëns van die dop Ek leef in. Maak dit meer draagbaar. So, ek hou van jou oplossing met behulp van csh script. Ek verleng net dit om te werk per rig in die localdirs te maak dit werk vir myself.

foreach dir ( $localdirs )
    echo ${path} | egrep -i "$dir" >& /dev/null
    if ($status != 0) then
        set path = ( $dir $path )
    endif
end

Die gebruik van sed (1) te verwyder duplikate.

$ PATH=$(echo $PATH | sed -e 's/$/:/;s/^/:/;s/:/::/g;:a;s#\(:[^:]\{1,\}:\)\(.*\)\1#\1\2#g;ta;s/::*/:/g;s/^://;s/:$//;')

Dit sal die duplikate verwyder nadat die eerste instansie, wat mag of nie mag nie wees wat jy wil hê, Bv:.

$ NEWPATH=/bin:/usr/bin:/bin:/usr/local/bin:/usr/local/bin:/bin
$ echo $NEWPATH | sed -e 's/$/:/; s/^/:/; s/:/::/g; :a; s#\(:[^:]\{1,\}:\)\(.*\)\1#\1\2#g; t a; s/::*/:/g; s/^://; s/:$//;'
/bin:/usr/bin:/usr/local/bin
$

Geniet dit!

Hier is wat ek gebruik - miskien iemand anders sal dit nuttig vind:

#!/bin/csh
#  ABSTRACT
#    /bin/csh function-like aliases for manipulating environment
#    variables containing paths.
#
#  BUGS
#    - These *MUST* be single line aliases to avoid parsing problems apparently related
#      to if-then-else
#    - Aliases currently perform tests in inefficient in order to avoid parsing problems
#    - Extremely fragile - use bash instead!!
#
#  AUTHOR
#    J. P. Abelanet - 11/11/10

#  Function-like alias to add a path to the front of an environment variable
#    containing colon (':') delimited paths, without path duplication
#
#  Usage: prepend_path ENVVARIABLE /path/to/prepend
alias prepend_path \
  'set arg2="\!:2";  if ($?\!:1 == 0) setenv \!:1 "$arg2";  if ($?\!:1 && $\!:1 !~ {,*:}"$arg2"{:*,}) setenv \!:1 "$arg2":"$\!:1";'

#  Function-like alias to add a path to the back of any environment variable 
#    containing colon (':') delimited paths, without path duplication
#
#  Usage: append_path ENVVARIABLE /path/to/append
alias append_path \
  'set arg2="\!:2";  if ($?\!:1 == 0) setenv \!:1 "$arg2";  if ($?\!:1 && $\!:1 !~ {,*:}"$arg2"{:*,}) setenv \!:1 "$\!:1":"$arg2";'

Ek stel altyd my pad van nuuts af in .cshrc. Dit is wat ek begin met 'n basiese pad, iets soos:

set path = (. ~/bin /bin /usr/bin /usr/ucb /usr/bin/X11)

(afhangende van die stelsel).

En dan doen:

set path = ($otherPath $path)

om meer dinge te voeg

Ek het dieselfde behoefte as die oorspronklike vraag. Bou op jou vorige antwoorde, het ek gebruik in Korn / POSIX / Bash:

export PATH=$(perl -e 'print join ":", grep {!$h{$_}++} split ":", "'$otherpath:$PATH\")

Ek het probleme om dit direk vertaal in csh (csh ontsnap reëls is mal). Ek het gebruik (soos voorgestel deur dr_pepper):

set path = ( `echo $otherpath $path | tr ' ' '\n' | perl -ne 'print $_ unless $h{$_}++' | tr '\n' ' '`)

Het jy idees het om te vereenvoudig dit meer (verminder die aantal pype)?

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top