簡體   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