Як об'єднати і передати результати двох різних команд в одну команду?


35

Я хочу об'єднати (об'єднати) вихід з двох різних команд і передати їх одній команді.

Дурний приклад:

Команди, які хочу об'єднати вихід:

cat wordlist.txt
ls ~/folder/*

в:

wc -l

У цьому прикладі, якщо wordlist.txt містить 5 рядків і 3 файли, я хочу wc -lповернути 8.

$cat wordlist.txt *[magical union thing]* ls ~/folder/* | wc -l
8

Як це зробити?

Відповіді:


56

Ваша магічна штука - це крапка з комою… і фігурні дужки:

    { cat wordlist.txt ; ls ~/folder/* ; } | wc -l

Фігурні дужки лише групують команди разом, щоб знак труби |впливав на комбінований вихід.

Ви також можете використовувати круглі дужки ()навколо групи команд, яка виконувала б команди в підзарядці. Це має тонкий набір відмінностей з фігурними брекетами, наприклад, спробуйте наступне:

    cd $HOME/Desktop ; (cd $HOME ; pwd) ; pwd
    cd $HOME/Desktop ; { cd $HOME ; pwd ; } ; pwd

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

Що стосується крапки з комою, до альтернативних варіантів відносяться знаки &&та ||, які умовно виконують другу команду, лише якщо перша є успішною або, якщо ні, відповідно, наприклад

    cd $HOME/project && make
    ls $HOME/project || echo "Directory not found."

1
Це працює! Допоможіть мені дізнатися - що саме тут роблять фігурні брекети? Які ще магічні сили вони мають?
Девід Онілл

@DavidOneill { list; }- складна команда . З bash(1): список просто виконується в поточному середовищі оболонки. список повинен бути завершений новим рядком або крапкою з комою. [..] Статус повернення - це статус виходу зі списку.
Лекенштейн

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

якщо; в цих командах не буде &&, якщо файл wordlist.txt не існує?
Rinzwind

Якщо wordlist.txtне існує помилки з, catвона з’явиться на стандартній помилці, але не на стандартному виході, тому wc -lне буде враховувати жодних рядків з неї. Те саме стосується і ~/folderнеіснуючих. Можна додати 2> /dev/nullміж кожною з цих команд та їх крапкою з комою, щоб запобігти шуму при стандартній помилці, але крім негарних, повідомлення про помилки нешкідливі для підрахунку рядків.
паблом

8

Оскільки wcприймає шлях до файлу як вхідний, ви також можете використовувати підстановку процесу:

wc -l <(cat wordlist.txt; ls ~/folder/*)

Це приблизно еквівалентно:

echo wordlist.txt > temp
ls ~/folder/* >> temp
wc -l temp

Розум, який ls ~/folder/*також повертає вміст підкаталогів, якщо такі є (через глобальне розширення). Якщо ви просто хочете перерахувати вміст ~/folder, просто скористайтеся ls ~/folder.


Це wc -lбув просто складений приклад, я фактично перетворюю його на щось складніше, що не має такої можливості.
Девід Онілл

2
@DavidOneill Ну, як catприймає аргумент файлу, ви можете використовувати cat <(cat wordlist.txt; ls wordlist.txt) | wc -lі навіть cat wordlist.txt <(ls wordlist.txt) | wc -l. Це, звичайно, дуже некрасиво, але це демонструє нескінченні можливості за допомогою інструментів командного рядка.
Лекенштейн

1
@DavidOneill Правильно, я виправив це зараз, дякую.
Лекенштейн

1
Ви хочете, ls ~/folder/щоб якщо ~/folderсимвольне посилання lsперераховує вміст його цілі, а не саме посилання. До речі, за всіма lsкомандами слід дотримуватися того, -1щоб надрукувався один файл на рядок і wc -lбув дійсним способом підрахунку файлів.
паблом

@pablomme Ви правдиво стосуєтесь символічного зв'язку, але -1мається на увазі, оскільки вихід - це не термінал, а труба.
Лекенштейн

2

Я задавав собі те саме питання, і закінчив писати короткий сценарій.

magicalUnionThing(Я це називаю append):

#!/bin/sh
cat /dev/stdin
$*

Зробіть цей сценарій виконуваним

chmod +x ./magicalUnionThing

Тепер ви робите

cat wordlist.txt |./magicalUnionThing ls ~/folder/* | wc -l

Що це робить:

  • Надіслати стандартний вхід на стандартний вихід
  • Виконати аргумент. $*повертає всі аргументи як рядок. Вихід цієї команди за замовчуванням йде на стандартний вихід сценарію.

Отже, stdout магічногоUnionThing буде його stdin + stdout команди, яка передається як аргумент.

Звичайно, є більш прості способи, як і в інших відповідях.
Можливо, ця альтернатива може бути корисною в деяких випадках.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.