我想遍歷從echo $VARIABLE
命令獲取的路徑列表。循環遍歷Bash中的路徑變量的元素
例如:
echo $MANPATH
將返回
/usr/lib:/usr/sfw/lib:/usr/info
所以這是三個不同的路徑,每個用冒號隔開。我想循環每個路徑。有沒有辦法做到這一點?謝謝。
感謝所有迄今爲止的回覆,看起來我實際上並不需要循環。我只需要一種方法去除冒號,這樣我就可以在這三條路徑上運行一條ls
命令。
我想遍歷從echo $VARIABLE
命令獲取的路徑列表。循環遍歷Bash中的路徑變量的元素
例如:
echo $MANPATH
將返回
/usr/lib:/usr/sfw/lib:/usr/info
所以這是三個不同的路徑,每個用冒號隔開。我想循環每個路徑。有沒有辦法做到這一點?謝謝。
感謝所有迄今爲止的回覆,看起來我實際上並不需要循環。我只需要一種方法去除冒號,這樣我就可以在這三條路徑上運行一條ls
命令。
您可以使用Bash的模式替換parameter expansion來填充您的循環變量。例如:
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循環解釋爲單獨的單詞,而不是單個字符串。
可以使用Bash對X在$ {}符號來實現:
for p in ${PATH//:/$'\n'} ; do
echo $p;
done
這不處理空格。 – codeforester 2017-05-30 19:40:36
可以設置內部字段分隔符:
(IFS=:
for p in $MANPATH; do
echo "$p"
done
)
我用了一個子shell所以在IFS的變化沒有反映在我目前的shell中。
我相信即使$ MANPATH包含空格,這也是可行的。 – user1277476 2012-07-25 20:01:14
是的!這是與包含空白的路徑(或任何IFS在您的系統上)一致的唯一答案。經過Cygwin,Fedora,Ubuntu測試,並在$ PATH上爲我工作 – hobs 2013-09-26 15:37:13
處理空間不錯,但不處理glob字符。 – codeforester 2017-05-30 20:36:35
for p in $(echo $MANPATH | tr ":" " ") ;do
echo $p
done
-1用於未加引號的變量插值,不希望的'echo'以及當shell可以執行替換時的子進程。 – tripleee 2012-07-25 18:43:22
它需要引號,但它比殼體內置的線路噪聲更具可讀性。詭計不是敵人。 – user1277476 2012-07-25 20:00:02
這不能通過加引號來解決(只),它至少還有一個@tripleee沒有提及的其他問題。請參閱[爲什麼printf比回顯更好?](https://unix.stackexchange.com/q/65803)。然而,目前非常低的分數看起來很苛刻,因爲它在功能上並不比公認的「解決方案」差得多。 – pjh 2017-08-24 16:36:10
的規範辦法做到這一點,在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
這樣就可以通過$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
IFS=:
arr=(${MANPATH})
for path in "${arr[@]}" ; do # <- quotes required
echo $path
done
...它確實照顧的空間:O),但也增加了空元素,如果你有這樣的:
:/usr/bin::/usr/lib:
...那麼指數0,2將是空的(」 「),不能說爲什麼指數4心不是設在所有
這不處理glob字符。 – pjh 2017-08-24 16:46:17
這也可以使用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
中)。包括目錄與在名字空間:
下面是通過在$HOME/.allbin
創建符號鏈接到在$PATH
每個文件和目錄縮短$PATH
變量的長度的示例。這不是爲日常使用是有用的,但是如果你在一個docker
容器得到too many arguments
錯誤消息,因爲bitbake
使用完整$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"
這應該理論上,還可以加快正常的shell使用和shell腳本,因爲搜索每個執行的命令的路徑更少。它是哈哈,雖然,所以我不建議任何人這樣縮短他們的$PATH
。
但是,foreachpath
別名可能派上用場。
如果它們包含空格呢? – 2015-01-07 16:06:54
據我瞭解,當任何子字符串包含空格時,這不起作用,這正是$ PATH使用非空格分隔符的原因。 @ choroba的答案在這方面是正確的。 – intelfx 2015-03-25 08:38:08
@intelfx:問題被標記爲[tag:linux]。如果你在Linux上的* MANPATH *中有空格,那麼你在做Linux錯誤。證明完畢 – 2015-03-25 14:12:46