子流程中的bash globbing

2024-04-25 00:29:27 发布

您现在位置:Python中文网/ 问答频道 /正文

如果我有一个目录,其中除了一个文件外,我可能会在bash中执行以下操作:

cd /tmp/a
rm -rf !(specialfile)
cd -

将其转换为最明显的Python代码对我来说失败了:

^{pr2}$

有了这个信息:

('', "/bin/sh: -c: line 0: syntax error near unexpected token `('\n/bin/sh: -c: line 0: `cd /tmp/a; rm -rf !(specialfile); cd -'\n")

Python中的第二个好处似乎是:

p = '/tmp/a'
    for i in os.listdir( p ):
    if i != 'specialfile':
        os.remove( os.path.join( p, i ) )

但当然,这并不能很好地处理文件和子目录。有更好的方法吗?在


Tags: 文件rm代码目录bash信息binos
2条回答

更新:正如@isedev和OP@JohnSchmitt在评论中指出的,subprocess.Popen调用sh,而不是{}(根据平台,sh可能是也可能不是{},这取决于平台),但是使用扩展模式匹配运算符!(...)需要(a)bash,同时(b)启用extglob选项(背景见下文)。在

因此,答案是:

  • 使用通过-c命令行选项传递的命令字符串显式调用bash。在
  • 通过-O命令行选项打开extglobshell选项(没有它,glob!(specialfile)会触发操作遇到的语法错误)。在

借用@JohnSchmitt自己的评论,我们得到:

subprocess.Popen("bash -O extglob -c 'cd /tmp/a; rm -rf !(file2); cd -'",
  stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate()

(不太优雅的替代方法是在rm命令之前,将shopt -s extglob;添加到bash命令字符串中。)

背景

!(specialfile)是一个扩展的模式匹配运算符的实例(请参见man bash,第Pattern Matching)部分;这些扩展运算符默认不启用;shopt -s extglob启用它们(shopt -u extglob禁用它们)。在

你可以用手术室步行正如@Bakuriu提到的。非常重要的一点是从下到上遍历目录树,以便始终保持空目录,但包含“specialfile”的目录除外。这就是为什么在os.rmdir命令中需要try子句。在

import os
for root, dirs, files in os.walk(top, topdown=False):
    for name in files:
        if name != 'specialfile':
            os.remove(os.path.join(root, name))
    for name in dirs:
        try:
            os.rmdir(os.path.join(root, name))
        except:
            pass

相关问题 更多 >