PATHからディレクトリを削除する


28

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

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


2
多くの技術がここに記載されています:stackoverflow.com/questions/370047/...
SLM

回答:


23

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

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

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

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

あなたの場合、あなたは

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

1
問題のパスがPATH変数の先頭にある場合、末尾のコロンと一致させる必要があります。これは、PATH変数の簡単な一般的な操作を複雑にする厄介な警告です。
グレアム14年

4
非常に多くのスラッシュを扱うとき、すべてのエスケープを防ぐために、正規表現の区切り文字/|:のようなものに変更することを好みPATH=$(echo "$PATH" | sed -e 's|:/d/Programme/cygwin/bin$||')ます。
マティアスクーン

17

bashの場合:

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行目は、指定されたコンポーネントを削除します。


@Gillesに感謝します。あなたの答えは、4つではなく3つのPATHの操作のみを必要とする独自のソリューションを思い付くように促しました。* 8 ')
マークブース

8

ここに示されている他のオプションを検討し、それらのいくつかがどのように機能するかを完全に理解していないので、私は自分の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:ifに変わりませんpath_remove mypath。これは以前のpath_remove機能で問題になりました。

bash文字列の操作方法の優れた説明は、Advanced Bash-Scripting Guideにあります。


6

そこで、@ gillesと@ bruno-a(および他のいくつかのsedトリック)からの回答を組み合わせて、この1ライナーを思い付きました。これは、最初に発生するかどうかに関係なく、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を追加するためのこのワンライナーを思いついたのは、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')

echo "$PATH:$ADD_PART"ADD_PARTを最初ではなくPATHの最後に追加する場合は、最後の部分を変更します。

...

...またはこれをさらに簡単にするには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)

きちんとした、たとえ私がそう言ったとしても:-)


私は提案、特にスクリプトに関するアイデアが好きです。
デボラス

3

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

export PATH = `echo $ PATH | tr ":" "\ n" | grep -v "anaconda" | tr "\ n" ":" `


2

パス変数からディレクトリを削除する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のソリューションから修正されたコードです。ここでは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
}

1

Tusharから受け入れられた回答を完成/改善するには、次の方法があります。

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

最終的には、次のような結果になります。

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

0

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

pattern=cygwin; export PATH=$(echo $PATH|tr ':' '\n'|sed "\#${pattern}#d" |tr '\n' ':')
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.