繁体   English   中英

命令在bash终端中运行,但在Python subprocess中不起作用。 获得“路径必须在表达式之前:'%p'错误

[英]Command working in bash terminal but not in Python subprocess.Popen(); getting a 'paths must precede expression: `%p' error

我正在尝试查找最近修改过的文件的位置。 在bash中,您可以通过

 find /media/tiwa/usb/ -not -path '*/\.*' -type f -printf '%T@ %p\n' 2> >(grep -v 'Permission denied' >&2) | sort -k1,1nr | head -1`

确实,在我的系统上,这返回

1527379702.1060795850 /media/tiwa/usb/hi.txt

我打算获取此命令的输出(在Python中),在第一个空格处将其分割,然后解析文件路径(是的,我可以使用awk ,但是无论如何都会抛出相同的错误)。 所以我做了

import subprocess
bashCommand = "find /media/tiwa/usb/ -not -path '*/\.*' -type f -printf '%T@ %p\n' 2> >(grep -v 'Permission denied' >&2) | sort -k1,1nr | head -1"
process = subprocess.Popen(bashCommand.split(), stdout=subprocess.PIPE)
output, error = process.communicate()
print(output)

但这打印出来

find: paths must precede expression: `%p'

转义反斜杠似乎也没有帮助。

是什么导致此问题,如何解决?

您有一个完整的shell命令行,而不仅仅是一个命令及其参数,这意味着您需要使用shell=True选项,而不是(错误地)将字符串拆分为多个字符串。 (Python字符串拆分不等同于shell的单词拆分,这涉及到更多的事情,也更加复杂。)此外,由于您的命令行包含bash特定的功能,因此您需要告诉Popen显式使用/bin/bash ,而不是默认/bin/sh

import subprocess
bashCommand = "find /media/tiwa/usb/ -not -path '*/\.*' -type f -printf '%T@ %p\n' 2> >(grep -v 'Permission denied' >&2) | sort -k1,1nr | head -1"
path_to_bash = "/bin/bash"  # or whatever is appropriate
process = subprocess.Popen(bashCommand, 
                           stdout=subprocess.PIPE, 
                           shell=True,
                           executable=path_to_bash)
output, error = process.communicate()
print(output)

(但是,使用os.walk()获取每个文件,并使用os.stat()获取每个相关文件的修改时间会更简单,更健壮,并且只保留到目前为止找到的最新文件,直到您已经检查了每个文件。

import os
newest = (0, "")
for (dir, subdirs, fname) in os.walk("/media/tiwa/usb"):
    if fname.startswith(".") or not os.path.isfile(fname):
        continue
    mtime = os.stat(fname).st_mtime
    if mtime > newest[0]:
        newest = (mtime, fname)

也许

def names_and_times(d):
    for (_, _, fname) in os.walk(d):
        if fname.startswith(".") or not os.path.isfile(fname):
            continue
        yield (os.stat(fname).st_mtime), fname)

newest = max(names_and_times("/media/tiwa/usb"))

请记住,上述任何一种方法都只会返回一个具有最新修改时间的文件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM