web-dev-qa-db-ja.com

PATHからのディレクトリの削除

MingWを使用してwxWidgetsをコンパイルしようとしています。パスにcygwinがあり、競合しているようです。だから私はPATH変数から/d/Programme/cygwin/binを削除したいと思います。これを行うためのエレガントな方法があるかどうか疑問に思います。

素朴なアプローチはそれをファイルにエコーし、手動で削除して調達することですが、これにはもっと良いアプローチがあると思います。

33
Devolus

$ PATHの値を「編集」するための標準ツールはありません(つまり、「フォルダーがまだ存在しない場合にのみ追加する」または「このフォルダーを削除する」)。あなたはただ実行します:

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

これを現在のセッションで使用します。変更したい場合は、.bashrc、bash.bashrc、/ etc/profileに追加してください-システムとユーザーのニーズに合うものなら何でも。ただし、BASHを使用している場合、たとえば、最後にあると想定して、PATH変数からディレクトリ/home/wrong/dir/を削除する場合は、次のことも実行できます。

PATH=$(echo "$PATH" | sed -e 's/:\/home\/wrong\/dir$//')

だからあなたの場合にはあなたが使うかもしれません

PATH=$(echo "$PATH" | sed -e 's/:\/d\/Programme\/cygwin\/bin$//')
28
tusharmakkar08

バッシュで:

directory_to_remove=/d/Programme/cygwin/bin
PATH=:$PATH:
PATH=${PATH//:$directory_to_remove:/:}
PATH=${PATH#:}; PATH=${PATH%:}

中間変数を使用しない場合は、ディレクトリ内の/文字を保護して削除し、検索テキストの末尾として扱われないようにする必要があります。

PATH=:$PATH:
PATH=${PATH//:\/d\/Programme\/cygwin\/bin:/:}
PATH=${PATH#:}; PATH=${PATH%:}

1行目と3行目は、検索パスのすべてのコンポーネントが:で囲まれるように配置して、最初と最後のコンポーネントの特殊なケースを避けるためにあります。 2行目は、指定されたコンポーネントを削除します。

ここに提示された他のオプションを検討した後、それらの一部がどのように機能するかを完全に理解していないので、私は自分でpath_remove関数を追加しました.bashrc

function path_remove {
  # Delete path by parts so we can never accidentally remove sub paths
  PATH=${PATH//":$1:"/":"} # delete any instances in the middle
  PATH=${PATH/#"$1:"/} # delete any instance at the beginning
  PATH=${PATH/%":$1"/} # delete any instance in the at the end
}

これは Gillesの解 にかなり近づきましたが、コマンドラインで簡単に使用できるbash関数としてラップされました。

これは、bash関数として、パス上のプログラムである必要なくプログラムのように機能し、実行するために外部プログラムを必要とせず、bash文字列操作のみを行うという利点があります。

かなり堅牢に見えますが、特にsomepath:mypath/mysubpathからsomepath/mysubpath:実行した場合path_remove mypath、これは以前の問題でしたpath_remove 関数。

Bash文字列操作がどのように機能するかについての優れた説明は Advanced Bash-Scripting Guide にあります。

9
Mark Booth

したがって、@ gillesと@ bruno-a(および他のいくつかのsedトリック)からの回答を組み合わせて、最初に発生したかどうかに関係なく、PATHから(すべての)REMOVE_PARTを削除するこのワンライナーを思い付きました、 PATHの途中または終わり

_PATH=$(REMOVE_PART="/d/Programme/cygwin/bin" sh -c 'echo ":$PATH:" | sed "s@:$REMOVE_PART:@:@g;s@^:\(.*\):\$@\1@"')
_

少し扱いに​​くいですが、1回のヒットで実行できるのは素晴らしいことです。 _;_は、2つの個別のsedコマンドを結合するために使用されます。

  • _s@:$REMOVE_PART:@:@g_(_:$REMOVE_PART:_を単一の_:_に置き換えます)
  • s@^:\(.*\):\$@\1@(echoコマンドで追加した先頭と末尾のコロンを削除します)

そして、同様の行に沿って、PATHにADD_PARTを追加するためのこの1行を思い付くことができましたonly PATHにまだ含まれていない場合

_PATH=$(ADD_PART="/d/Programme/cygwin/bin" sh -c 'if echo ":$PATH:" | grep -q ":$ADD_PART:"; then echo "$PATH"; else echo "$ADD_PART:$PATH"; fi')
_

ADD_PARTをPATHの先頭ではなく末尾に追加する場合は、最後の部分を_echo "$PATH:$ADD_PART"_に変更します。

...

...またはこれをさらに簡単にするには、_remove_path_part_というスクリプトを作成し、内容を指定します

_echo ":$PATH:" | sed "s@:$1:@:@g;s@^:\(.*\):\$@\1@"
_

そして、内容を含む_prepend_path_part_というスクリプト

_if echo ":$PATH:" | grep -q ":$1:"; then echo "$PATH"; else echo "$1:$PATH"; fi
_

そして、内容を含む_append_path_part_というスクリプト

_if echo ":$PATH:" | grep -q ":$1:"; then echo "$PATH"; else echo "$PATH:$1"; fi
_

それらをすべて実行可能にしてから、次のように呼び出します。

  • PATH=$(remove_path_part /d/Programme/cygwin/bin)
  • PATH=$(prepend_path_part /d/Programme/cygwin/bin)
  • PATH=$(append_path_part /d/Programme/cygwin/bin)

きちんと、私が自分でそう言っても:-)

7
Lurchman

はるかにシンプルなワンライナー。

pATH = `echo $ PATHのエクスポート| tr ":" "\ n" | grep -v "anaconda" | tr "\ n" ":" `

5
user332870

パス変数からディレクトリを削除するbash関数を作成するのは興味深い演習です。

これは、パスにディレクトリを追加/追加するために.bash *ファイルで使用するいくつかの関数です。重複するエントリがあれば削除するという利点があり、コロンで区切られたあらゆる種類のパス変数(PATH、MANPATH、INFOPATHなど)で機能します。 remove_from関数は、ディレクトリを削除します。

# {app,pre}pend_to path-var-name dirpath
# remove_from path-var-name dirpath
#
# Functions to manipulate a path-style variable.  {app,pre}pend_to
# both remove any other instances of dirname before adding it to
# the start or end of the path-var-name variable.
#
# Calling example:
#   append_to PATH "/usr/local/bin"
#
# Uses eval to allow target path varname to be passed in.
function remove_from() {
  # add surrounging colons
  eval tmp_path=":\$${1}:"
  # if dir is already there, remove it
  (echo "${tmp_path}" | grep --silent ":${2}:") &&
    tmp_path=`echo "$tmp_path" | sed "s=:${2}:=:=g"`
  # remove surrounding colons
  tmp_path=`echo "$tmp_path" | sed 's=^:==; s=:$=='`
  eval export $1=\"$tmp_path\"
}
function append_to() {
  remove_from "$1" "$2"  # clean the path contents
  eval export $1=\"\$${1}:$2\"
}
function prepend_to() {
  remove_from "$1" "$2"  # clean the path contents
  eval export $1=\"${2}:\$$1\"
}
2
Greg Tarsa

以下は、Greg Tarsaのソリューションから改訂されたコードです。ここでは、bash組み込みコマンドのみが使用されます。したがって、多くのfork()システムコールが節約されます。

# Calling example:
#   append_to PATH "/usr/local/bin"

function remove_from()
{
    local path="${1}"
    local dir="${2}"
    local -a dirs=()
    local old_ifs="${IFS}"
    IFS=":"
    set -- ${!path}
    while [ "$#" -gt "0" ]
    do
        [ "${1}" != "${dir}" ] && dirs+=("${1}")
        shift
        done
    eval "export ${path}=\"${dirs[*]}\""
    IFS="${old_ifs}"
}

function append_to()
{
    remove_from "${1}" "${2}"
    [ -d "${2}" ] || return
    if [ -n "${!1}" ]
    then
        eval "export ${1}=\"${!1}:${2}\""
    else
        eval "export ${1}=\"${2}\""
    fi
}

function prepend_to()
{
    remove_from "${1}" "${2}"
    [ -d "${2}" ] || return
    if [ -n "${!1}" ]
    then
        eval "export ${1}=\"${2}:${!1}\""
    else
        eval "export ${1}=\"${2}\""
    fi
}
2
Jie Gong

このメソッドは、開始/終了パス区切り文字を処理します。

echo $PATH | sed 's/:/\n/g' | grep -v <path description> | xargs | tr ' ' ':'

説明:

echo $ PATH変数をsedに入れ、「:」を改行に置き換えます

grep出力し、クエリに一致する行を削除します

xargs改行をスペースに置き換える出力

trスペースをコロンに置き換える出力

xargsは末尾の値のトリミングを処理します

いくつかのgrepsをチェーンして一連のパスを削除する

1
anax32

Tusharから受け入れられた回答を完成/改善するには、次のことができます。

  • スラッシュ以外の区切り文字を使用して、PATH内のスラッシュをエスケープする必要がないようにします。
  • -eオプション、 sedのmanページ に従って: "-e、-expression、-f、または--fileオプションが指定されていない場合、最初の非オプション引数が解釈するsedスクリプト。」
  • g(グローバル)フラグを使用して、すべての出現箇所を削除します

最後に、それはこのようなものを与えます:

PATH=$(echo "$PATH" | sed 's@:/home/wrong/dir$@@g')
1
Bruno A.

現在の回答は、複数のパスを削除する必要があるという点で、私の同様の問題を解決しません。これらのパスはすべて、1つのディレクトリのサブディレクトリです。その場合、このワンライナーは私のために機能します:(パター​​ンがcygwinであると仮定します。つまり、cygwinを含むすべてのパスを削除します)

pattern=cygwin; export PATH=$(echo $PATH|tr ':' '\n'|sed "\#${pattern}#d" |tr '\n' ':')
0
Penghe Geng