В каталоге много txt-файлов.
Если я time wc -l *.txt | head
это сделаю, то это займет
real 0m0.032s
user 0m0.020s
sys 0m0.008s
Если я time wc -l *.txt | tail
это сделаю, то это займет
real 0m0.156s
user 0m0.076s
sys 0m0.088s
Означает ли это, что wc
он будет знать заранее, что он перенаправляется в head, и будет учитывать только первые 10 файлов и экономить время? Другими словами, он знает о конвейере? И это что-то особенное wc
или это относится ко всем стандартным/встроенным командам?
решение1
Я сделал a strace
для обеих команд. Интересно, что когда вы передаете вывод в конвейер, head
то есть только 123 системных вызова. С другой стороны, когда вы передаете в конвейер в tail, то есть 245 системных вызовов (или больше, если файлов *.txt больше).
Корпус: голова
Вот последние несколько строк при передаче по конвейеру head
:
open("file12.txt", O_RDONLY) = 3
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
read(3, "", 16384) = 0
write(1, "0 file12.txt\n", 13) = -1 EPIPE (Broken pipe)
--- SIGPIPE (Broken pipe) @ 0 (0) ---
+++ killed by SIGPIPE +++
При wc
попытке записать вывод 12-го файла он получает ошибку EPIPE
. Вот почему head
вышел после получения 11-й строки. При head
выходе wc
получает SIGPIPE
. Как видно из вывода strace выше, wc
сначала пытается записать в этот канал (откуда head
больше не читает) и получает ошибку, что канал сломан.
Сигнал SIGPIPE отправляется процессу, когда он пытается записать данные в канал без процесса, подключенного к другому концу. -- fromВикипедия
Корпус: хвост
При конвейеризации в tail
, ничего подобного выше нет. wc завершается изящно после записи всего вывода в конвейер, к которому tail
нужно подключиться на все время. tail
нужны все строки, прежде чем он сможет напечатать последние 10 из них. Когда больше нет вывода для чтения, tail
печатает строки и также изящно завершает работу
решение2
Любой процесс, который не блокируется, SIGPIPE
будет завершен, если его вывод попадет на конец записи канала, с которого никто не выполняет чтение.
Поэтому, как только head
закрывает свой вход (т.е. завершает работу), wc
он умирает, что занимает меньше времени, чем завершение всей работы.
решение3
Вы можете сделать это, чтобы ваши файлы исчезли:
time wc -l *.txt > tee | tail
Но немного вы добавляете время для команды ти time
.
С tee command
:
root@debian:/home/mohsen/test# time wc -l *.txt > tee | tail
real 0m0.005s
user 0m0.000s
sys 0m0.000s
Без tee command
:
root@debian:/home/mohsen/test# time wc -l *.txt | tail
8 f3.txt
7 fi.txt
5 mydata.txt
4 newfile.txt
4 t1.txt
4 t2.txt
5 test.txt
4 text.txt
0 t.txt
49 total
real 0m0.004s
user 0m0.000s
sys 0m0.000s