2013-02-22 2 views
2

Я пытаюсь запустить эту команду BASH в Popen:Python эквивалент найти -exec

find /tmp/mount -type f -name "*.rpmsave" -exec rm -f {} \; 

Но каждый раз, когда я получаю: «найти: отсутствующий аргумент` -exec '\ п»в STDERR ,

Каким будет эквивалент python?

Мой наивный Подход будет:

for (root,files,subdirs) in os.walk('/tmp/mount'): 
    for file in files: 
     if '.rpmsave' in file: 
      os.remove(file) 

наверняка есть лучше, вещий способ сделать это?

ответ

4

Вы на самом деле есть два вопроса - первый, почему ваша Popen конструкция не работает, а во-вторых, как использовать os.walk правильно , Нед ответил на второй, поэтому я обращусь к первому: вам нужно знать об утечке оболочки. \; является экранированным ;, так как обычно ; будет интерпретироваться Bash как разделяющий две команды оболочки и не будет передан find. (В некоторых других оболочках также должно быть экранировано {}.)

Но с Popen вы обычно не хотите использовать оболочку, если можете ее избежать. Таким образом, это должно сработать:

import subprocess 

subprocess.Popen(('find', '/tmp/mount', '-type', 'f', 
        '-name', '*.rpmsave', '-exec', 'rm', '-f', '{}', ';')) 
+0

Я полагаю, вы я прав, я пробовал каждую комбинацию списка команд, потому что раньше у меня был опыт использования команд Popen, но я не понимал деталей фактической команды find, которую я использовал. Это сделало трюк, и в моем конкретном контексте это было лучшее решение, чем os.walk. Спасибо. –

+0

вы можете использовать '' rm ',' -f ',' - ',' {} ',' + '', чтобы разрешить файлы, начинающиеся с' -', и передать более одного имени файла в 'rm' на время. – jfs

2

У вас есть в основном способ сделать это. У вас есть три разные вещи, которые вы координируете: 1) ходить по дереву, 2) работать только с файлами .rpmsave и 3) удалять эти файлы. Где бы вы нашли что-то, что изначально сделало все это, не сказав это? Команда Bash и код Python имеют одинаковую сложность, что неудивительно.

Но вы должны исправить свой код, например:

for root,files,subdirs in os.walk('/tmp/mount'): 
    for file in files: 
     if file.endswith('.rpmsave'): 
      os.remove(os.path.join(root, file)) 
+0

подкачки '' files' и subdirs' – jfs

1

Если вы обнаружите, что делаете это много. Это может быть полезным оберткой os.walk:

def files(dir): 
    # note you have subdirs and files flipped in your code 
    for root,subdirs,files in os.walk(dir): 
     for file in files: 
     yield os.path.join(root,file) 

Чтобы удалить кучу файлов с определенным расширением внутри директории:

[os.remove(file) for file in files(directory) if file.endswith('.extension')]