解析命令行字符串到子进程列表的最简单方法?



我想弄清楚如何使用subprocess.run()运行这个命令:

cmd = 'find / ( -path /mnt -prune -o -path /dev -prune -o -path /proc -prune -o -path /sys -prune ) -o ! -type l -type f -or -type d -printf "depth="%d/"perm="%m/"size="%s/"atime="%A@/"mtime"=%T@/"ctime"=%C@/"hardlinks"=%n/"selinux_context"=%Z/"user="%u/"group="%g/"name="%p/"type="%Y\n'

我已经将命令放入列表中,甚至删除了项目等:

cmd = [
'find',
'/',
'( -path /mnt -prune -o -path /dev -prune -o -path /proc -prune -o -path /sys -prune )',
'-o',
'! -type l',
'-type f',
'-or',
'-type d'
]

我已经尝试使用/bin/bash运行命令:

cmd = '/bin/bash -c find / ( -path /mnt -prune -o -path /dev -prune -o -path /proc -prune -o -path /sys -prune ) -o ! -type l -type f -or -type d -printf "depth="%d/"perm="%m/"size="%s/"atime="%A@/"mtime"=%T@/"ctime"=%C@/"hardlinks"=%n/"selinux_context"=%Z/"user="%u/"group="%g/"name="%p/"type="%Y\n'

并不重要。我试过的所有方法都不起作用。要么我没有得到任何输出,要么它列出了我的主目录中的文件,要么我得到一个错误,例如:b'find: paths must precede expression: ! -type lnUsage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]n'

是否有任何简单的方法可以在命令行中执行命令,并将字符串解析为subprocess.run()想要的任何列表元素?

使用shlex.split()进行解析

修复了printf字符串中不正确的引号后,我们得到:

cmd = r'''
find / ( -path /mnt -prune -o -path /dev -prune -o -path /proc -prune -o -path /sys -prune ) -o ! -type l -type f -or -type d -printf 'depth=%d/perm=%m/size=%s/atime=%A@/mtime=%T@/ctime=%C@/hardlinks=%n/selinux_context=%Z/user=%u/group=%g/name=%p/type=%Y\n'
'''
print(shlex.split(cmd))

…它会发出一个完全正确的结果,subprocess.call()可以正常工作。


手工构建正确的命令行

关于手工操作的样子:

cmd = [
'find', '/',
'(',
'-path', '/mnt',  '-prune',
'-o', '-path', '/dev',  '-prune',
'-o', '-path', '/proc', '-prune',
'-o', '-path', '/sys',  '-prune',
')',
'-o', '!', '-type', 'l',
'-type', 'f',
'-or',
'-type', 'd',
'-printf', 'depth=%d/perm=%m/size=%s/atime=%A@/mtime=%T@/ctime=%C@/hardlinks=%n/selinux_context=%Z/user=%u/group=%g/name=%p/type=%Yn'
]

注意:

  • 语法引号改变了shell的解析模式,它们不会成为数据的一部分。"foo"变成了foo;"foo"bar"baz"变成foobarbaz。所以你不能/不应该/不要尝试在Python传入的数据中加上这些引号。
  • 对于(也是如此:反斜杠是shell语法。它实际上并没有成为find的参数之一,所以您可以忽略它。
  • 任何没有引号或转义的空格分隔单词;所以shell中的-type f就是'-type', 'f',两个独立的单词。