Перетворення декількох файлів за допомогою програм, які приймають stdin і виводять їх у stdout


0

Я хочу перетворити список файлів у каталозі в інший каталог, використовуючи деякі програми попередньої обробки.

Я знаю, що можу зробити це для одного файлу:

cat "$INDIR/$file" | ./program > "$OUTDIR/$file"

І я знаю, що можу зробити це для декількох файлів:

for file in $(ls -1 $INDIR); do
    cat "$INDIR/$file" | ./program > "$OUTDIR/$file";
done

Але проблема в тому ./program вимагає деякого часу для ініціалізації, і я не хочу, щоб накладні витрати були повторені, оскільки всередині буде багато файлів $INDIR, і мій підхід вище завжди перезавантажуватиме ./program для кожного файлу в каталозі. Це повільно.

Тому моє запитання: Чи є спосіб зробити моє завдання вище без повторної ініціалізації ./program, у bash?

(редагувати після @grawity) Розуміючи, що ми не можемо просто подавати всі файли за один раз в stdin ./program щоб мати можливість відокремити вихідний сигнал, я очікую, що зможе мати функцію create_into_pipeline що робить щось на зразок цього:

process_pipeline = create_into_pipeline(./program.pl | ./program.py | ./program.bash | ./program);
for file in $(ls -1 $INDIR); do
    process_pipeline < cat "$INDIR/$file" > "$OUTDIR/$file.new";
done

Якщо це неможливо, то, напевно, я піду зі створенням скрипта Python, який буде діяти як веб-сервер і викликати ./program по мірі необхідності. Але я хочу знати, чи можу я зробити це в bash, оскільки я вважаю, що він буде більш ефективним у часі, ніж у Python (ви також можете довести, що ця помилка є неправильною, і я піду вперед з Python).


Декілька деталей

The ./program насправді послідовність програм, що передаються один одному, як такі:

./program.pl | ./program.py | ./program.bash | ./program

Я розглядав кожну програму, щоб використовувати опцію для обробки одного каталогу файлів і виведення в інший каталог, зберігаючи імена файлів. Але оскільки у мене є чотири програми, я не хочу створювати три тимчасові каталоги, оскільки доступ до жорсткого диска буде повільним. Отже, я не хочу цього:

./program.pl $INDIR $OUTDIR;
./program.py $INDIR $OUTDIR;
./program.bash $INDIR $OUTDIR;
./program $INDIR $OUTDIR;

Просто додаткову інформацію, якщо вона може змінити відповідь (і фактично остання програма ./program не має такої можливості для обробки каталогу, тому я не можу йти з цим підходом).


Напевно, ви маєте на увазі for file in $INDIR/*; do?
grawity

Внутрішній запис занадто багато $INDIR, так що я не можу це зробити.
justhalf

Відповіді:


2

Ні, це неможливо - принаймні, не без переписування самих програм.

Наразі кожна з ваших програм очікує рівно один файл у своєму stdin. Частина або інша частина їх ініціалізації встановлює стан, що відноситься до обробки цього єдиного файлу. Вони виконують цю ініціалізацію, потім продовжують читати з stdin, поки не натискають "end of file", а потім виходять.

Тут є дві проблеми. Перша полягає в тому, що труба не має інших кордонів, ніж "кінець файлу" (коли автор закриває свій кінець). Ви повинні були б створити якусь особливу синхронізацію, щоб визначити, коли закінчується файл і починається інший файл. (Можливо, пакети, що складаються з даних довжини +, з порожнім пакетом, що позначає кінець файлу.) Вам також знадобиться спеціальна версія cat що підтримує це.

Друга проблема полягає в тому, що деякі програми, самі по собі, Не чекайте більше одного файлу в їх stdin. Кожен з них повинен бути переписаний на 1) зрозуміти схему синхронізації для правильного розділення декількох файлів на stdin; 2) переміщення обробки в цикл, для кожного файлу зчитування; 3) повторно ініціалізувати частину пам'яті перед обробкою кожного файлу (це багато в чому залежить від того, що робить кожна програма).

Примітка: Ви говорите, що "остання програма ./програма не має такої можливості для обробки каталогу". Я припускаю, що інші програми робити є такий варіант. Це означає, що для цих програм, № 2 і № 3 є вже реалізовано і може бути просто підключено до коду stdin з декількома файлами (крок # 1, який вам все одно доведеться реалізувати у всіх програмах).


Дякуємо за відповідь! Хороші моменти щодо меж, які існують при використанні труб. Що стосується кроку # 2 і # 3 для інших програм, вони все ще очікують назви каталогу, тому вони не можуть бути пов'язані без використання жорсткого диска, якого я хочу уникнути. Я додав більш детальну інформацію про моє очікування щодо самого питання, сподіваюся, що ви зможете оновити свою відповідь, якщо це необхідно.
justhalf

@justhalf: Відповідь залишається незмінною. У створенні трубопроводу немає магії; воно, по суті, додає стандартний висновок однієї програми до чужого stdin, нічого більше. Він не може чарівно вирішити, яка частина програми повинна бути запущена один раз і яка повторюється для кожного входу.
grawity
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.