命令在bash终端中工作但不在Python subprocess.Popen();获得一条路径必须先于表达式:`%p'错误

时间:2018-05-27 00:23:57

标签: python linux bash subprocess

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

执行此操作
 // extract 'go' from 'iamgoodhere'
 string s = "iamgoodhere";
 int start = 3, end = 4;
 cout<<s.substr(start,end-start+1); // go

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

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

我打算获取此命令的输出(在Python中),将其拆分在第一个空格上,并解析文件路径(是的,我可以使用1527379702.1060795850 /media/tiwa/usb/hi.txt ,但无论如何都会抛出相同的错误)。所以我做了

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)

逃避反斜杠似乎没有帮助。

导致此问题的原因是什么,我该如何解决?

1 个答案:

答案 0 :(得分:2)

你有一个完整的shell命令行,而不仅仅是一个命令加上它的参数,这意味着你需要使用shell=True选项而不是(错误地)将字符串拆分成多个字符串。 (Python字符串拆分不等同于shell的单词拆分,这更加复杂和复杂。)此外,由于您的命令行包含bash特定功能,您需要告诉Popen使用{明确{1}},而不是默认的/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)

请注意,上述任何方法都只会返回一个文件,并且修改时间最短。