реализация piped xargs rm и tee в скрипт Python - PullRequest
0 голосов
/ 17 января 2019

У меня есть скрипт Python, который печатает имена файлов в соответствии с конкретными шаблонами и характеристиками. Затем я направляю несколько команд в этот распечатанный список, и xargs rm удаляет перечисленные файлы. Этот скрипт запускается на сервере Unix, и обычно я запускаю скрипт следующим образом:

python deletefiles.py <directory> <wildcard1> | tee deletedfiles.txt | xargs rm

все работает нормально, но я пытаюсь найти способ, чтобы команды tee и xargs rm уже были в сценарии, чтобы пользователю не приходилось вводить их в команду.

Я посмотрел в Интернете, и люди говорят import subprocess, но я не понимаю полный синтаксис того, как использовать его в сочетании с моим сценарием.

на данный момент код для запуска в Unix-системе просто

if len(sys.argv) == 3:
    try:
        input_directory = sys.argv[1]
        input_delete = sys.argv[2].split(',') \\patterns to delete
    except ValueError:
        "Please enter a valid input"

то, что я пытаюсь сделать, это реализовать проверку другого аргумента, проанализировать / удалить, где analyze просто позволяет скрипту выполнять свою работу по распечатке имен файлов, а если аргумент delete, скрипт будет xargs rm и tee эти файлы.

Я не уверен в том, как к этому приблизиться, так как большая точка печати файлов с моим скриптом на python была такова, что xargs rm и tee deletedfiles.txt есть что-то, что можно удалить при удалении / сохранении в текстовый файл. мне было интересно, есть ли способ сделать это условно в скрипте Python

если мне нужно предоставить больше информации о моем сценарии, я с радостью обязуюсь

Ответы [ 2 ]

0 голосов
/ 17 января 2019

Вы можете запустить их как подпроцесс. Хотя есть лучшая альтернатива; см. ниже.

Предполагая, что files содержит ваши имена файлов,

from subprocess import Popen, PIPE
p = subprocess.Popen("tee '{0}' | xargs rm".format(teefile),
    shell=True, stdin=PIPE)
p.communicate('\n'.join(files))

Тем не менее, обе операции тривиально выполнять в Python.

with open(teefile, "w") as tee:
    for file in files:
        tee.write(file + '\n')
        os.unlink(file)

Я думаю, вы согласитесь, что последний проще и элегантнее (хотя в Python 3 subprocess также можно сделать намного проще; вы действительно хотите подготовиться к переходу на Python 3 как можно скорее.)

0 голосов
/ 17 января 2019

Я изначально собирался просто сделать комментарий, но я думаю, что это легче понять.

Python имеет модуль argparse для обработки аргументов командной строки. Примеры немного сбивают с толку, поэтому я бы рекомендовал просто смотреть на get_args ниже, пока это не станет понятным.

Вместо того, чтобы пытаться передать его на tee и xargs rm, вы можете сделать все это в самом скрипте python.

Вот пример, из которого вы можете построить:

#!/usr/bin/env python2

# allows us to use python3 print function
from __future__ import print_function

import os
import fnmatch
import sys
import argparse


def get_args():
    parser = argparse.ArgumentParser()
    # note directory has `required=True`, that means the user must provide it
    parser.add_argument("--directory", help="Directory to analyze", required=True)
    # store_true stores a boolean depending on whether or not the flag was present
    parser.add_argument("--delete", help="Delete the files which should be removed", action="store_true", default=False)
    args = parser.parse_args() # parses, makes sure all conditions are met, exits if user didn't provide a filename
    return args


def analyze(directory):
    # do whatever wildcarding here to return a list of files
    # heres just an example, remove all *.txt files recursively
    files_to_delete = []
    for root, dirnames, filenames in os.walk(directory):
        # fnmatch is unix-like filename matching
        for filename in fnmatch.filter(filenames, "*.txt"):
            # abspath gives us the full path, root is the original directory
            files_to_delete.append(os.path.abspath(os.path.join(root, filename)))
    return files_to_delete


def delete(files):
    # write to deleted_files.txt in this function
    deleted_file = open("deleted_files.txt", 'w')
    for f in files:
        if os.path.exists(f): # filepath exists
            if os.path.isfile(f): # is a file (not a directory)
                os.remove(f) # remove it
                deleted_file.write("{}\n".format(f)) # write to the file
            else:
                print("Could not remove {}, is not a file".format(f), file=sys.stderr)
        else:
            print("Could not remove {}, does not exist".format(f), file=sys.stderr)
    deleted_file.close()


def main():
    args = get_args()
    files = analyze(args.directory)
    # if the user gave us the --delete flag
    if args.delete:
        delete(files)
    else:
        # just print it out to the user
        for f in files:
            print(f)

if __name__ == "__main__":
    main()

Если вы просто хотите сохранить, какие файлы должны быть удалены, перенаправьте вывод в файл

python2.7 deletefiles.py --directory test_dir > files_to_delete.txt

Если вы хотите удалить их:

python2.7 deletefiles.py --directory test_dir --delete

и затем вы можете cat deleted_files.txt получить файлы, которые были удалены.

Вот некоторая документация для функций, которые я использовал:

fnmatch.filter, sys.stderr, os.path.join, os.path.abspath, os.path.isfile, os.walk, os.remove

Если вы хотите удалить каталоги, взгляните на os.removedirs

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...