36

echo $VARIABLEコマンドから取得したパスリストをループしたい。

例えば:

echo $MANPATH戻ります

/usr/lib:/usr/sfw/lib:/usr/info

つまり、これは3つの異なるパスであり、それぞれがコロンで区切られています。これらの各パスをループしたいと思います。それを行う方法はありますか?ありがとう。

これまでのすべての返信に感謝しますが、結局ループは必要ないようです。lsこれらの3つのパスで1つのコマンドを実行できるように、コロンを削除する方法が必要です。

4

10 に答える 10

62

内部フィールドセパレータを設定できます。

( IFS=:
  for p in $MANPATH; do
      echo "$p"
  done
)

サブシェルを使用したので、IFSの変更は現在のシェルに反映されません。

于 2012-07-25T18:05:46.053 に答える
18

Bashでこれを行うための標準的な方法は、read組み込みを適切に使用することです。

IFS=: read -r -d '' -a path_array < <(printf '%s:\0' "$MANPATH")

これが唯一の堅牢なソリューションです。必要な処理を正確に実行します。区切り文字で文字列を分割し、スペース、改行、および、などの:グロブ文字に関して安全です(他の回答とは異なり、すべて壊れています)。*[ ]

このコマンドの後に、配列がpath_array作成され、ループすることができます。

for p in "${path_array[@]}"; do
    printf '%s\n' "$p"
done
于 2015-04-29T16:43:39.873 に答える
17

Bashのパターン置換パラメーター展開を使用して、ループ変数を設定できます。例えば:

MANPATH=/usr/lib:/usr/sfw/lib:/usr/info

# Replace colons with spaces to create list.
for path in ${MANPATH//:/ }; do
    echo "$path"
done

注:置換展開を引用符で囲まないでください。MANPATHからの展開された値を、単一の文字列としてではなく、forループによって個別の単語として解釈する必要があります。

于 2012-07-25T18:04:37.863 に答える
5

このようにして、ループの内側でも外側でも同じまま$PATHで、単一のループで安全に通過できます。$IFS

while IFS=: read -d: -r path; do # `$IFS` is only set for the `read` command
    echo $path
done <<< "${PATH:+"${PATH}:"}"   # append an extra ':' if `$PATH` is set

$IFS、の値を確認できます

IFS='xxxxxxxx'
while IFS=: read -d: -r path; do
    echo "${IFS}${path}"
done <<< "${PATH:+"${PATH}:"}"

出力は次のようになります。

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

StackExchangeに関する別の質問への参照。

于 2015-06-24T04:00:37.563 に答える
1
for p in $(echo $MANPATH | tr ":" " ") ;do
    echo $p
done
于 2012-07-25T18:09:34.677 に答える
1
IFS=:
arr=(${MANPATH})
for path in "${arr[@]}" ; do # <- quotes required
   echo $path
done

...スペースを処理します:o)が、次のようなものがある場合は空の要素も追加します:

:/usr/bin::/usr/lib:

...その後、インデックス0,2は空('')になり、インデックス4がまったく設定されていない理由はわかりません

于 2015-09-11T02:19:57.607 に答える
1

これは、コマンドラインでPythonを使用して解決することもできます。

python -c "import os,sys;[os.system(' '.join(sys.argv[1:]).format(p)) for p in os.getenv('PATH').split(':')]" echo {}

またはエイリアスとして:

alias foreachpath="python -c \"import os,sys;[os.system(' '.join(sys.argv[1:]).format(p)) for p in os.getenv('PATH').split(':')]\""

使用例:

foreachpath echo {}

このアプローチの利点は{}、各パスに連続して置き換えられることです。これを使用して、あらゆる種類のコマンドを作成できます。たとえば、のディレクトリ内のすべてのファイルとディレクトリのサイズを一覧表示できます$PATH。名前にスペースが含まれるディレクトリを含める:

foreachpath 'for e in "{}"/*; do du -h "$e"; done'

$PATH内のすべてのファイルとディレクトリへのシンボリックリンクを作成することにより、変数の長$PATHさを短縮する例を次に示します$HOME/.allbin。これは日常の使用には役立ちませんが、コマンドラインの一部としてfullを使用するため、コンテナにエラーメッセージが表示される場合に役立つことがあります...too many argumentsdockerbitbake$PATH

mkdir -p "$HOME/.allbin"
python -c "import os,sys;[os.system(' '.join(sys.argv[1:]).format(p)) for p in os.getenv('PATH').split(':')]" 'for e in "{}"/*; do ln -sf "$e" "$HOME/.allbin/$(basename $e)"; done'
export PATH="$HOME/.allbin"

これにより、理論的には、実行されるすべてのコマンドを検索するパスが少なくなるため、通常のシェルの使用とシェルスクリプトが高速化されます。ただし、かなりハッキーなので、このように短くすることお勧めしませ$PATH

ただし、foreachpathエイリアスは便利な場合があります。

于 2018-03-08T10:43:02.093 に答える
0

これを実現するために、${}表記のXのBashを使用できます。

for p in ${PATH//:/$'\n'} ; do
    echo $p;
done
于 2012-07-25T18:04:57.693 に答える
0

からのアイデアを組み合わせる:

コード:

PATHVAR='foo:bar baz:spam:eggs:'  # demo path with space and empty
printf '%s:\0' "$PATHVAR" | while IFS=: read -d: -r p; do
    echo $p
done | cat -n

出力:

1   foo
2   bar baz
3   spam
4   eggs
5   
于 2019-03-04T03:53:44.910 に答える
0

OPの更新では、結果のフォルダーが必要であり、スペースで区切られたリストのみが必要であるlsことが指摘されています。ls

ls $(echo $PATH | tr ':' ' ')素晴らしくてシンプルで、法案にうまく合うはずです。

于 2022-01-08T20:08:37.813 に答える