Эксперимент показывает, что это не работает.
Я создал 2-мегабайтный файл из /dev/urandom
, а затем попробовал указанную выше команду. Вот результаты:
% ls -l
total 41008
-rw-r--r-- 1 kst kst 20971520 2012-01-18 03:47 file
-rw-r--r-- 1 kst kst 20971520 2012-01-18 02:48 orig
% gzip -c file | dd of=file
0+1 records in
0+1 records out
25 bytes (25 B) copied, 0.000118005 s, 212 kB/s
% ls -l
total 20508
-rw-r--r-- 1 kst kst 25 2012-01-18 03:47 file
-rw-r--r-- 1 kst kst 20971520 2012-01-18 02:48 orig
$
Очевидно, что 2-мегабайтный случайный файл не будет сжиматься до 25 байт, и на самом деле при запуске gunzip
для сжатого файла получается пустой файл.
Я получил аналогичные результаты для гораздо меньшего случайного файла (100 байт).
Так что же случилось?
В этом случае команда dd
усекает file
до нуля байтов перед началом записи в него; gzip
начал чтение из нового пустого файла и выдал 25 байтов вывода, который затем dd
добавлялся в пустой file
. (Пустой файл "сжимается" до ненулевого размера; для любого компрессора теоретически невозможно сделать все входные данные меньшими).
Другие результаты могут быть возможны, в зависимости от времени процессов gzip
, dd
и shell, все из которых работают параллельно.
Есть условие гонки, потому что один процесс, gzip
, читает из file
, в то время как другой параллельный процесс, оболочка, пишет в него.
Должна быть возможность реализовать встроенный файловый компрессор, который читает и записывает в один и тот же файл, используя любую внутреннюю буферизацию, необходимую для предотвращения скопления данных. Но я никогда не слышал о том, чтобы кто-нибудь на самом деле реализовывал это, возможно потому, что это обычно не нужно и потому что если компрессор не работает на полпути, файл будет навсегда поврежден.