Любой способ выполнить команду piped в Python с использованием модуля подпроцесса, не используя shell = True?

Я хочу запустить командную строку linux/ bash с помощью командной строки из Python, которая сначала записывает файлы, а затем разбивает файл tar. Команда будет выглядеть как-то в bash:

> tar -cvf - path_to_archive/* | split -b 20m -d -a 5 - "archive.tar.split"

Я знаю, что могу выполнить его с помощью подпроцесса, с помощью параметров shell = True и отправки всей команды в виде строки, например:

import subprocess    

subprocess.call("tar -cvf - path_to_archive/* | split -b 20m -d -a 5 - 'archive.tar.split'", shell=True)

... но по соображениям безопасности я хотел бы найти способ пропустить часть "shell = True" (которая берет список строк, а не полную строку командной строки и не может обрабатывать канал char правильно). Есть ли решение для этого в Python? I.e., возможно ли каким-либо образом установить связанные каналы или какое-то другое решение?

Ответ 1

tar может разделить себя:

tar -L 1000000 -F name-script.sh cf split.tar largefile1 largefile2 ...

name- script.sh

#!/bin/bash
echo "${TAR_ARCHIVE/_part*.tar/}"_part"${TAR_VOLUME}".tar >&"${TAR_FD}"

Для повторной сборки

tar -M -F name-script.sh cf split.tar

Добавьте это в свою программу python.

Ответ 2

Если вы хотите избежать использования оболочки = True, вы можете вручную использовать подпроцессные каналы.

from subprocess import Popen, PIPE
p1 = Popen(["tar", "-cvf", "-", "path_to_archive"], stdout=PIPE)
p2 = Popen(["split", "-b", "20m", "-d", "-a", "5", "-", "'archive.tar.split'"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]

Обратите внимание, что если вы не используете оболочку, у вас не будет доступа к расширению таких символов, как *. Вместо этого вы можете использовать модуль glob.

Ответ 3

Есть ли причина, по которой вы не можете использовать tarfile? | http://docs.python.org/library/tarfile.html

import tarfile
tar = tarfile.open("sample.tar.gz")
tar.extractall()
tar.close()

Просто напишите как файл, похожий на объект, используя tarfile, а не вызывайте подпроцесс.

Ответ 4

Бесстыдный плагин, я написал оболочку подпроцесса для упрощения командной строки в python: https://github.com/houqp/shell.py

Пример:

shell.ex("tar -cvf - path_to_archive") | "split -b 20m -d -a 5 - 'archive.tar.split'"