首页 > 解决方案 > 如何在 xonsh 子进程中扩展 shell 变量?

问题描述

我正在学习xonsh。我尝试了以下简单的脚本,但它在zipinfo -1 $mzip_str,特别是在扩展时失败了mzip_str

#!/usr/bin/env xonsh

from pathlib import Path

my_path = Path('/path/to/downloads/')

dir_list = my_path.glob('*.zip')
for my_zip in dir_list:
  mzip_str = str(my_zip)
  zip_dir_names = $(zipinfo -1 $mzip_str | grep -E '.*/$')
  print(zip_dir_names)

在 xonsh shell 中,我得到以下结果:

➤ zip_dir_names = $(zipinfo -1 mzip_str)
zipinfo:  cannot find or open mzip_str, mzip_str.zip or mzip_str.ZIP.

➤ zip_dir_names = $(zipinfo -1 $mzip_str)
zipinfo:  cannot find or open $mzip_str, $mzip_str.zip or $mzip_str.ZIP.

➤ zip_dir_names = $(zipinfo -1 @mzip_str)
zipinfo:  cannot find or open @mzip_str, @mzip_str.zip or @mzip_str.ZIP.

➤ zip_dir_names = $(zipinfo -1 !mzip_str)
zipinfo:  cannot find or open mzip_str, mzip_str.zip or mzip_str.ZIP.

标签: shellxonsh

解决方案


来自官方教程

运算符形式在子进程模式下@(<expr>)工作,并将评估任意 Python 代码。结果被附加到子进程命令列表中。如果结果是字符串或字节,则将其附加到参数列表中。如果结果是列表或其他非字符串序列,则将内容转换为字符串并按顺序附加到参数列表中。如果第一个位置的结果是一个函数,它被视为别名(参见下面的别名部分),即使它没有显式添加到aliases映射中。否则,结果将自动转换为字符串。

所以相关的行应该看起来像(未经测试,因为我没有安装这个xonsh):

zip_dir_names = $(zipinfo -1 @(my_zip) | grep -E '.*/$')

但这听起来像$()返回一个字符串,zip_dir_names如果你想用它做任何事情但打印它,你可能想成为一个列表。就像是

zip_dir_names = [ name for name in !(zipinfo -1 @(my_zip)) if name.endsWith("/") ]

可能会更好。当然,或者只是使用标准的 Python zipfile 模块模块而不是外部程序。

zip_dir_names = [ f.filename for f in ZipFile(my_zip).infolist() if f.is_dir() ]

推荐阅读