$ PATHのパスを個別に表示する方法


45

さまざまなパスを$PATH個別にリストする方法がわからないため、次のようになります。

/bin
/usr/bin
/usr/local/bin

誰もこれの正しい変数を知っていますか?


各パスは別々の行にしてください
HankG

パスに改行が含まれる場合、何を印刷する必要がありますか?
マーティン


回答:


57

試してくださいsed

$ sed 's/:/\n/g' <<< "$PATH"

またはtr

$ tr ':' '\n' <<< "$PATH"

またはpython

$ python2 -c "import os; print os.environ['PATH'].replace(':', '\n')"

ここでは、上記のすべてがのすべての出現:を新しい行に置き換えます\n


pythonアプローチのバリエーション:python -c 'import sys;print sys.argv[1].replace(":","\n")' $PATH
Sergiy Kolodyazhnyy

Pythonの別のバリエーション、ちょっとpython -c "print r'$PATH'.replace(':', '\n')"
ハッキング:(

3
tr私のために働いた(Mac、ところで)。ありがとう。
マイクS.

彼らにそれを追加したい人、私のようなものについては.bash_profile、このようにそれを追加しますalias path='tr ":" "\n" <<< "$PATH"'
マイク・S.

63

bashのパラメーター展開を使用します。

echo "${PATH//:/$'\n'}"

これにより、すべて:$PATH改行(\n)に置き換えられ、結果が出力されます。の内容は$PATH変更されません。
最初ののみを置き換える場合は:、2番目のスラッシュを削除します。echo -e "${PATH/:/\n}"


3
これは純粋な bashで行われるため、これが最良のソリューションだと思います。
ryanmjacobs

1
@ryanmjacobs少し好奇心が強い:私のソリューションは何を使うと思いますか?:D
ムル

1
仕組みを説明してください。
Tulainsコルドバ

そのような操作は何と呼ばれますか?sedに似ていますが、sedではありません。Webで検索して詳細を確認できるように、その名前は何ですか。
Tulainsコルドバ

3
私の回答のリンク(パラメーター拡張)をたどり、最後の2番目のセクションまでスクロールダウン${parameter/pattern/string}
Cyrus

27

IFSの使用:

(set -f; IFS=:; printf "%s\n" $PATH)

IFSbashが分割する文字を保持するため、IFSwith :はbashで$PATHon の展開を分割し:ます。printf引数が使い果たされるまで、書式文字列で引数をループします。set -fPATHディレクトリ名のワイルドカードが展開されないように、グロビング(ワイルドカード展開)を無効にする必要があります。


2
これはバックスラッシュとスペースで正しく機能します!
heinrich5991

14

を使用してxargs

xargs -n1 -d: <<< $PATH

から man xargs

-n max-args
          Use  at  most  max-args  arguments per command line.

 -d delim
          Input  items  are terminated by the specified character.

echo $PATH | xargs -n1 -d: echo冗長であるか、それは問題ではないなど、これのバリエーションでしょうか?
セルギーKolodyazhnyy

@Serg echo $PATH | xargs -n1 -d: は同じことを行いますが、もう1つシェルを使用します。最初のものはecho $PATH、出力を評価して次のシェルにパイプし、残りを実行します。
souravc

7

Goに相当するものを次に示します。

$ cat path.go
package main

import (
    "fmt"
    "os"
    "strings"
)

func main() {
    for _, p := range strings.Split(os.Getenv("PATH"), ":") {
        fmt.Println(p)
    }
}

$ go run path.go
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
/home/nathan/.local/bin
/home/nathan/go/bin

7

さらにいくつかのアプローチがあります。私は、PATHバックスラッシュ、スペース、さらにcut改行を含むディレクトリを使用して、それらがすべてで動作することを示しています(改行で失敗するものを除く):

$ echo "$PATH"
/bin:usr/bin/:/usr/local/bin:/some\ horrible thing:/even 
new lines
  • Perlのいくつかの方法:

    $ perl -pe 's/:/\n/g' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines

    -p手段は「によって与えられたスクリプトを適用した後、すべての入力行を印刷します-e」。スクリプトは、置換演算子(s/oldnew/)を使用してすべて:を改行に置き換えています。

    $ perl -lne 'print for split /:/' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines

    -lそれぞれに改行を追加しますprintコール。ここでは、スクリプトは入力を分割し、:各分割要素をループして出力します。

    $ perl -F: -ane '$"="\n";print "@F"' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines

    -a作るのperlと同じように動作awk:それはによって与えられた文字の上にその入力ラインのそれぞれを分割します-F(そう:、ここでは)、配列に結果を保存します@F$"その値が印刷されたリストの各要素との間に印刷される特殊なPerlの変数、「区切り」、です。したがって、改行に設定すると、のprint @list各要素が印刷され@list、次に改行が印刷されます。ここでは、印刷に使用しています@F

    $ perl -F: -ane 'print join "\n", @F' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines

    上記と同じ考えですが、ゴルフは少なくなります。を使用する代わりに、改行を使用して配列を$"明示的に入力joinしてから印刷します。

  • grepPCREマジックで簡単:

    $ grep -oP '(^|:)\K[^:]+' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines

    -oせるには、grep各マッチが別の行に印刷されているように、各ラインの唯一の一致部分を印刷します。これ-Pにより、Perl Compatible Regular Expressions(PCRE)が有効になります。正規表現は、行の先頭()または文字の後に続く非:[^:]+)のストレッチを探しています。これは「この時点より前に一致したものをすべて破棄する」ことを意味するPCREトリックであり、ここでも印刷を回避するために使用されます。 ^:\K:

  • そしてcut解決策(これは改行で失敗しますが、バックスラッシュとスペースを扱うことができます):

    $ cut -d: -f 1- --output-delimiter=$'\n' <<<"$PATH"
    /bin
    usr/bin/
    /usr/local/bin
    /some\ horrible thing
    /even 
    new lines

    使用されるオプション-d:は、入力区切り文字をに設定することです。これは、すべてのフィールドを(最初から最後まで)印刷し:、出力区切り文字を設定すること-f 1-を意味します--output-delimiter=$'\n'。これ$'\n'ANSI Cの引用であり、シェルで改行文字を印刷する方法です。

上記のすべての例で、私はbash(および他のシェル)のstring<<<)演算子を使用して、文字列をプログラムへの入力として渡します。はとcommand <<<"foo"同等echo -n "foo" | commandです。私はいつも引用"$PATH"符なしで引用していることに注意してください、シェルは改行文字を食べていたでしょう。


@ 7studコメントに別のアプローチを示しましたが、これは含めるにはあまりにも良いことです。

$ perl -0x3a -l012 -pe '' <<<"$PATH"

それがゴルフとして知られているものです。-0進又は16進数で入力レコードセパレータを指定します。これが「行」を定義するものであり、そのデフォルト値は\n改行文字です。ここ:ではx3a、16進数のaに設定しています(try printf '\x3a\n')。-l3つのことを行います。まず$/、各行の末尾から入力レコード区切り文字()を削除し(実質的に:ここを削除します$\)、次に、出力レコード区切り文字()を指定された8進値または16進値(012is \n)に設定します。$\が定義されている場合、各print呼び出しの最後に追加されるため、各に改行が追加されますprint

-pe意志pはによって与えられたスクリプトを適用した後、各入力ラインをRINT -e。上記のオプションフラグによってすべての作業が行われるため、ここにはスクリプトはありません!


あなたのperl oneライナーは不明瞭ではありません!他のスイッチがすべてを処理するため、-eスイッチを実行するコードがないバージョンを次に示しますperl -0x3a -l012 -pe '' <<<$PATH。説明:-0入力レコード区切り文字を設定します(16進/ 8進表記で指定、x3Aはコロンです)、-l2つのことを行います:1)入力レコード区切り文字を削除し、2)出力レコード区切り文字が指定されている場合は設定します(8進表記) 、012は改行です)。-p各なります$ _の値は、外ループプリントラインは読ま。
7stud

また、-Fがこれらを自動的にオンに-Fするため、使用する例では-aand -nフラグを削除できることに注意してくださいperl -F: -e 'print(join "\n", @F);' <<<$PATHperlrunを参照してください。素敵な例。
7スタッド

@ 7studうわー、それは本当に素晴らしいです、ありがとう!恥知らずに盗まれ、私の答えに追加されました(気にしないと思うので、自分で答えとして自由に投稿してください。それを削除します)。そして-F情報をありがとう。私は長年にわたって-Fと組み合わせて使用してきましたが-an、他のものが暗示されていることに気付きませんでした。ちなみに、SergがCode Golfについて言及しているのを見ましたが、この種のことに興味があるなら、UnixとLinuxも楽しむと思います。
テルドン

ねえ、ありがとう。このステートメントに関する説明の1つ:最後に、-l各印刷呼び出しの最後に指定された出力レコード区切り文字も追加します。 実際、printは、出力レコード区切り$/文字が定義されている場合、常に出力レコード区切り文字を文字列の末尾に追加します。デフォルトではundefです。したがって、-ljusはを設定し$/、それによりprintは文字列の最後に改行を追加します。
7スタッド

私はあなたが気にしないと思います -全くそうではありません。:)
7stud

6

この答えでは:

  1. C
  2. Python
  3. ルビー
  4. 代替awk

1. C

すべてのスクリプト言語がすでに使用されているため、Cを使用します。get_env()関数を使用して環境変数を取得するのは非常に簡単です(GNU Cライブラリのドキュメントを参照)。残りは単なる文字操作です

bash-4.3$ cat get_path.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char *path = getenv("PATH");
    int length = strlen(path) -1;
    for(int i=0;i<=length;i++){
        if (path[i] == ':')
            path[i] = '\n';
        printf("%c",path[i]);
    }
    printf("\n");
    return 0;
}
bash-4.3$ gcc get_path.c
bash-4.3$ ./a.out 
/home/xieerqi/bin
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin
/opt/microchip/xc16/v1.25/bin
/opt/microchip/xc32/v1.40/bin
/opt/microchip/xc8/v1.35/bin
/home/xieerqi/bin
/home/xieerqi/bin/sh

2. Python

しかし、「なぜ」ではないため、コマンドライン引数を介した代替のPythonバージョンもあります sys.argv

python -c 'import sys; print "\n".join(sys.argv[1].split(":"))' "$PATH"

3.ルビー

CコンパイラやPythonインタプリタとは異なり、RubyにはデフォルトではUbuntuが付属していませんが、Rubyでの解決策は次のようになります。

ruby -ne 'puts $_.split(":")' <<< "$PATH"

コメントの 7stud(ありがとうございます!)で示唆されているように、これは

ruby -F: -ane 'puts $F' <<<$PATH

そしてこのように

ruby -0072 -ne 'puts chomp' <<<$PATH

4.代替のawk

split()関数を利用して、読み取った行を配列に分解し、for-eachループを使用して各項目を別々の行に出力できます。

awk '{split($0,arr,":"); for(var in arr) print arr[var]}' <<< $PATH

1
素敵なルビーの例。 puts配列の要素を別々の行に自動的に出力します!:あなたはまた、スイッチは、分割を行うことができますruby -F: -ane 'puts $F' <<<$PATH :説明-Fセット$;($;ゼロのデフォルト値は、空白で分割を持っている)文字列で使用されるデフォルトの区切り::分割で指定した文字に。 -a$ _。splitを呼び出します。$ _はgets()を使用して読み込まれた行で、結果の配列をに割り当て$Fます。
-7スタッド

@ 7studやあ、ありがとう!:) -Fフラグがあることを知りませんでした-私はRubyで始めたばかりなので、少し粗雑な方法でやっています。
セルギーコロディアズニー

いいえ、これはあいまいです。あなたの1つのライナーは非常に読みやすく、明快さはいつも簡潔さよりも優先されるはずです。
7stud

うん 短いものを見つけました: ruby -0072 -ne 'puts chomp' <<<$PATH。説明:-0入力レコード分離文字を設定します(8進形式の文字を指定します。072はコロンです)。Rubyは、Perlと同様の方法で$ _を使用します。gets()メソッド(-nループで使用)は、読み込まれた現在の行に $ _を設定します。chomp()引数なしでは、$ _を削除します。私はまだあなたのものが好きです。:)
7stud

実際、@ 7studは、先ほど投稿した-Fフラグ付きのものが短くなっています。そうした場合、echo "ruby -F: -ane 'puts $F' <<<$PATH" |wc -c それはそれは271です私に語った、バイト、しかし進数の1が、コマンド全体のためだ276で我々は唯一のコード自体を考えると、当然のことながら、 puts $F明らかに短いです。:)ところで、あなたはコードゴルフについて知っていますか?最短バイト数でパズルをプログラミングするためのソリューションのサイトです。これに関連する質問があります:codegolf.stackexchange.com/q/96334/55572
Sergiy Kolodyazhnyy

5

おそらく言及されていない唯一の方法は、私が何年も使用してきた方法です:

echo $PATH | tr ":" "\n"

そのため、.profileまたは.bash_profileなどに次を追加できます。

alias path='echo $PATH | tr ":" "\n"'


1
この答えはすでにそれを述べた..
heemayl

ええ、でも私はエイリアスの提案が好きです。
7スタッド

4

さらにJavaが必要です!

public class GetPathByLine {
    public static void main(String[] args) {
        for (String p : System.getenv("PATH").split(":")) {
            System.out.println(p);
        }
    }
}

これをGetPathByLine.javaに保存し、次を使用してコンパイルします。

javac GetPathByLine.java

で実行:

java GetPathByLine

┌─[17:06:55]─[kazwolfe@BlackHawk]
└──> ~ $ cat GetPathByLine.java 
public class GetPathByLine {
    public static void main(String[] args) {
        for (String p : System.getenv("PATH").split(":")) {
            System.out.println(p);
        }
    }
}
┌─[17:06:58]─[kazwolfe@BlackHawk]
└──> ~ $ javac GetPathByLine.java 
┌─[17:07:02]─[kazwolfe@BlackHawk]
└──> ~ $ java GetPathByLine 
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin

うわー、これはやり過ぎです。Python 3では1行でこれを行うことができますpython3 -c "import os; [print(p) for p in os.getenv('PATH').split(':')]"
。– wjandrea

1
@wjandreaそれがポイントです!:D
カズウォルフ

3

awkを通じて。

echo $PATH | awk -F: '{for(i=1;i<=NF;i++)print $i}'

Python経由。

$ echo $PATH | python3 -c 'import fileinput
for line in fileinput.input():
    for i in line.split(":"):
        print(i)'

Pythonではインデントが非常に重要であることに注意してください。


短いawk:echo $PATH | awk '{gsub(/\:/,"\n");print}'
Sergiy Kolodyazhnyy

私はfileinputあなたがちょうどあなたがちょうど使用できるときに悩む理由がわかりませんinputpython3 -c 'print(*input().split(":"), sep="\n")' <<< "$PATH"
wjandrea

2

私はStephen Collyerの「Bash Path Functions」を使用しています(Linux Journalの彼の記事を参照)。これにより、シェルプログラミングでデータ型として「コロン区切りリスト」を使用できます。たとえば、次の方法で現在のディレクトリ内のすべてのディレクトリのリストを作成できます。

dirs="";for i in * ; do if [ -d $i ] ; then addpath -p dirs $i; fi; done  

次に、listpath -p dirsリストを作成します。


2

@Cyrus回答の説明

echo "${PATH//:/$'\n'}"

ノート:

ANSI-C引用 -$ 'some \ ntext'の説明

シェルパラメーターの展開 -$ {parameter / pattern / string}について説明します。パターンが「/」で始まる場合、パターンの一致はすべてストリングに置き換えられます。

だから私たちは持っています:

  1. 「/」で始まるパターン/:すべての一致を置き換える
  2. 改行記号(\ n)を処理するために$ 'anytext'縮約で引用された文字列$ '\ n'

1

別のAWKの方法は、個別のフィールドとしてではなく、個別のレコードとして各ディレクトリを扱うことです。

awk 'BEGIN{RS=":"} {print $0}' <<<"$PATH"

この構文は特に直感的です。ただし、必要に応じて、print $0暗黙的にすることで短縮できます(デフォルトのアクションであり1、true と評価され、すべての行で実行されます)。

awk 'BEGIN{RS=":"} 1' <<<"$PATH"

AWKのデフォルトの入力および出力レコード区切り文字は改行(改行)です。入力を読み取る前に入力レコード区切り文字(RS)を設定することにより:、AWKはコロンで区切ら$PATHれたディレクトリ名を構成ディレクトリ名に自動的に解析します。AWKは$0各レコード全体に展開され、改行は出力レコードのセパレーターのままであり、ループやgsub不要です。

ek@Io:~$ echo "$PATH"
/home/ek/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
ek@Io:~$ awk 'BEGIN{RS=":"} {print $0}' <<<"$PATH"
/home/ek/bin
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin

AWKは多くの場合、レコードを個別のフィールドに解析するために使用されますが、ディレクトリ名のリストを作成するためだけにその必要はありません。

これは、空白(スペースとタブ)、連続する複数の空白を含む入力に対しても機能します。

ek@Io:~$ awk 'BEGIN{RS=":"} {print $0}' <<<$'ab\t\t c:de    fg:h'
ab               c
de    fg
h

つまり、AWKでレコードを再構築しない限り(以下を参照)、入力にスペースまたはタブ(デフォルトのフィールドセパレーター)が含まれていても問題はありません。あなたはPATHおそらくUbuntuシステム上にスペースが含まれていませんが、それがない場合、これはまだ動作します。


これは、フィールドの集合として記録を解釈するAWKの能力があること、サイドノートとして、言及する価値だとなったディレクトリのテーブル構築の関連問題のために便利なコンポーネントを

ek@Io:~$ awk -F/ 'BEGIN{RS=":"; OFS="\t"} {$1=$1; print $0}' <<<"$PATH"
        home    ek      bin
        usr     local   sbin
        usr     local   bin
        usr     sbin
        usr     bin
        sbin
        bin
        usr     games
        usr     local   games
        snap    bin

好奇心$1=$1assignment 盛な割り当ては、AWK にレコードの再構築を強制する目的に役立ちます。

(これはおそらく、表を単に印刷するという正確な例よりも、コンポーネントで追加の処理を行う場合に役立つでしょう。)



0

$ PATHのパスを個別に表示する方法

これらは、それぞれのユースケースと互換性とリソース使用量に関する懸念に基づいて、これを行うための好ましい方法です。

tr

まず、覚えやすくて読みやすい迅速な解決策が必要な場合は、それをエコーPATHしてパイプして翻訳(trし、コロンを改行に変換します。

echo $PATH | tr : "\n"

パイプが原因で2つのプロセスを使用するというデメリットがありますが、単に端末をハッキングしているだけであれば、それを本当に気にしますか?

Bashのシェルパラメーター展開

.bashrcインタラクティブな使用のためにかなり永続的なソリューションが必要な場合は、次のコマンドをにエイリアスできますがpath、このソリューションの可読性は疑問です。

alias path="echo \"${PATH//:/$'\n'}\""

パターンが「/」で始まる場合、パターンのすべての一致は文字列に置き換えられます。通常、最初の一致のみが置き換えられます。

上記のコマンドは、Bashのシェルパラメーター展開を使用してコロンを改行に置き換えます。

${parameter/pattern/string}

説明するには:

          # v--v---------delimiters, a'la sed
echo "${PATH//:/$'\n'}"
          #  ^^ ^^^^^----string, $ required to get newline character.
          #   \----------pattern, / required to substitute for *every* :.

ただし、コマンドラインでエイリアスを作成していない場合は、コマンドラインでハッキングしているときにこれを思い出してください。

IFS、BashおよびDashでテスト済み

あるいは、シェル以外に依存しない、かなり相互互換性があり、読み取り可能で、理解可能なアプローチは、次の関数を使用することです(私はあなたに提案します.bashrc)。

次の関数は、内部(または入力)フィールドセパレーター(IFS)を一時的にコロンにし、配列が渡されるprintfと、配列が使い果たされるまで実行されます。

path () {
    local IFS=:
    printf "%s\n" ${PATH}
    }

この方法機能の作成IFSおよびprintfPOSIXによって提供されている、それは(Ubuntuは通常、別名、特にダッシュ、貝殻ほとんどのようなPOSIXで動作するはずですのでsh)。

Python

これにはPythonを使用する必要がありますか?あなたは出来る。これは、これについて考えることができる最短のPythonコマンドです。

python -c "print('\n'.join('${PATH}'.split(':')))"

またはPython 3のみ(そしておそらくもっと読みやすい?):

python3 -c "print(*'${PATH}'.split(':'), sep='\n')"

Pythonを持っている限り、これらは通常のシェル環境でも動作するはずです。


0

このソリューションは、JavaCgoおよびawkソリューションよりも簡単です。

$ LPATH=$PATH wine cmd /c echo %LPATH::=$'\n'% 2> /dev/null
/usr/local/bin
/usr/local/sbin
/usr/bin
/usr/sbin

別の素晴らしい可能性があります:

$ jrunscript -classpath /usr/share/java/bsh.jar -e 'print(java.lang.System.getenv("PATH").replaceAll(":","\n"))'
/usr/local/bin
/usr/local/sbin
/usr/bin
/usr/sbin

これには、いくつかの依存関係をインストールする必要があります。

sudo apt-get install openjdk-8-jdk-headless bsh
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.