循环遍历Bash中路径变量的元素

时间:2012-07-25 17:59:40

标签: linux bash

我想遍历一个我从echo $VARIABLE命令获得的路径列表。

例如:

echo $MANPATH将返回

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

这是三条不同的路径,每条路径用冒号分隔。我想循环每个路径。有没有办法做到这一点?感谢。

感谢到目前为止的所有回复,看起来我实际上根本不需要循环。我只需要一种取出冒号的方法,这样我就可以在这三条路径上运行一个ls命令。

9 个答案:

答案 0 :(得分:47)

您可以设置内部字段分隔符:

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

我使用了子shell,因此IFS中的更改不会反映在我当前的shell中。

答案 1 :(得分:16)

您可以使用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循环解释为单独的单词,而不是单个字符串。

答案 2 :(得分:12)

在Bash中执行此操作的规范方法是适当地使用ReviewController editReview内置函数:

read

这是唯一可行的解​​决方案:将完全按照您的意愿执行操作:在分隔符IFS=: read -r -d '' -a path_array < <(printf '%s:\0' "$MANPATH") 上拆分字符串,并且对于空格,换行符和全局字符(如:,{{)是安全的1}}等等(与其他答案不一样:它们都被打破了。)

执行此命令后,您将拥有一个数组*,您可以在其上循环:

[ ]

答案 3 :(得分:4)

通过这种方式,您可以通过一个循环安全地浏览$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

参考another question on StackExchange

答案 4 :(得分: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变量长度的示例。这对于日常使用没有用,但如果在too many arguments容器中收到docker错误消息,则可能非常有用,因为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" 1}}作为命令行的一部分...

$PATH

理论上,这也应该加速常规shell使用和shell脚本,因为搜索每个执行命令的路径较少。但 非常hacky,所以我不建议任何人以这种方式缩短foreachpath

export class LocationComponent { lat; lon; constructor() { } go(form) { form.lat=this.lat; form.lon=this.lon this.mapService.esri.go(form.lon, form.lat); this.dialogRef.close(); } changeLatLon(value:any){ let latlog=value.split(','); this.lat=latlog[0]; this.lon=latlog.length>1?latlog[1]:0; //if latlon haven't a ",", // latlong.length=1 } }别名可能会派上用场。

答案 5 :(得分:0)

您可以在$ {}表示法中使用Bash代替X来完成此操作:

for p in ${PATH//:/$'\n'} ; do
    echo $p;
done

答案 6 :(得分:0)

for p in $(echo $MANPATH | tr ":" " ") ;do
    echo $p
done

答案 7 :(得分:0)

IFS=:
arr=(${MANPATH})
for path in "${arr[@]}" ; do # <- quotes required
   echo $path
done

...它确实处理空格:o)但如果你有类似的东西,还会添加空元素:

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

...然后索引0,2将为空(''),不能说为什么索引4根本没有设置

答案 8 :(得分: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