Сообщить об ошибке.

Конвейер в стиле Bash и модуль sh в Python

Конвейер в стиле Bash можно построить с использованием композиции вызываемых функций. Для этого необходимо передать одну команду в качестве ввода другой, а модуль sh отправит вывод внутренней команды на ввод внешней:

import sh
# сортирует каталог от самого большого файла
# эквивалентно команде bash $ du | sort -rn
print(sh.sort(sh.du(), '-rn'))
# длинный вывод

# количество папок и файлов в /etc
# эквивалентно команде bash $ ls /etc -1 | wc -l
>>> print(sh.wc(sh.ls("/etc", "-1"), "-l"))
# 275

Примечание. Этот базовый конвейер не передает данные асинхронно, внутренняя команда блокируется до завершения перед отправкой данных внешней команде.

По умолчанию все переданные команды выполняются последовательно. Это означает, что сначала выполняется внутренняя команда, а затем отправляются данные внешней команде.

В приведенном выше примере команда терминала ls выполняется, собирая свои выходные данные, а затем отправляет их в команду wc. Это нормально для простых команд, но для команд, где требуется параллелизм, этого недостаточно. Возьмем следующий пример:

for line in sh.tr(sh.tail("-f", "test.log"), "[:upper:]", "[:lower:]", _iter=True):
    print(line)

Здесь необходимо, чтобы команда терминала tail отправляла свой вывод в команду tr по мере его получения данных. Пример, представленный выше, не сработает, потому что команда tail -f никогда не завершается, так как любая команда, которая передает другую команду по конвейеру, ожидает ее завершения. Такое поведение можно изменить с помощью специального ключевого слова _piped в передаваемой команде, который сообщает - не завершать работу перед отправкой данных, а отправлять свои данные постепенно.

for line in sh.tr(sh.tail("-f", "test.log", _piped=True), "[:upper:]", "[:lower:]", _iter=True):
    print(line)

Этот пример будет работать как ожидается, сообщая команде терминала tail -f, что она используется в конвейере, и должна посылать свой вывод построчно команде tr. По умолчанию, аргумент _piped отправляет STDOUT, но можно легко заставить его отправлять STDERR вместо этого, используя _piped='err'.