Команда работает в терминале bash, но не в подпроцессе Python.Popen ();получение пути 'должно предшествовать выражению: ошибка "% p" - PullRequest
0 голосов
/ 27 мая 2018

Я пытаюсь найти местоположение файла, который был недавно изменен.В 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'

Экранирование обратной косой черты тоже не помогает.

Что является причиной этой проблемы и какмне решить?

1 Ответ

0 голосов
/ 27 мая 2018

У вас есть целая командная строка оболочки, а не только одна команда плюс ее аргументы, что означает, что вам нужно использовать опцию shell=True вместо (ошибочного) разделения строки на несколько строк.(Разделение строк в Python не эквивалентно разделению слов в оболочке, что намного сложнее и сложнее.) Кроме того, поскольку ваша командная строка содержит 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"))

)

Имейте в виду, чтолюбой из предыдущих подходов вернет один файл с самым новым временем модификации.

...