Тому що це особливість оболонки (ksh, скопійована bash), і тільки оболонки.
/dev/tcp/...
не є реальними файлами, оболонка перехоплює спроби перенаправлення до /dev/tcp/...
файлу, а потім робить socket(...);connect(...)
(здійснює з'єднання TCP) замість open("/dev/tcp/..."...)
(відкриває цей файл) у цьому випадку.
Зауважте, що це має бути написано так. cat < /dev/./tcp/...
або ///dev/tcp/...
не працюватиме, і спробує натомість відкрити ті файли (яких у більшості систем не існує, і ви отримаєте помилку).
Напрямок перенаправлення також не має значення. Чи використовуєте ви 3< /dev/tcp/...
або 3> /dev/tcp/...
чи 3<> /dev/tcp/...
або навіть 3>> /dev/tcp/...
не буде ніякої різниці, ви будете мати можливість читати і писати з / в цей файловий дескриптор для прийому даних / відправки через цей TCP сокет.
Коли ви це робите cat /dev/tcp/...
, це не працює, тому cat
що не реалізує таку саму спеціальну обробку, вона робить open("/dev/tcp/...")
аналогічну для кожного файлу (крім -
), робить тільки оболонку (ksh, bash) і лише для цілі переадресацій.
Це cat -
ще один приклад файлу, який обробляється спеціально. Замість того, щоб робити a open("-")
, він читає безпосередньо з дескриптора файлів 0 (stdin). cat
і багато текстових утиліт роблять це, оболонка не робить для свого переадресації. Щоб прочитати вміст -
файлу, вам потрібно cat ./-
або cat < -
(або cat - < -
). У системах, у яких немає /dev/stdin
, bash
буде зроблено щось подібне для перенаправлення з цього (віртуального) файлу. GNU awk
робить те ж саме /dev/stdin
, /dev/stdout
, /dev/stderr
навіть в системах , які мають такі файли , які можуть викликати деякі сюрпризи на системи , такі як Linux , де ці файли поводяться по- різному.
zsh
також є підтримка сокетів TCP (і потік домену Unix), але це робиться з ztcp
(і zsocket
) вбудованими, тому це менш обмежено, ніж підхід ksh / bash. Зокрема, він також може діяти як сервер, який ksh / bash не може зробити. Це все ще набагато обмежено, ніж те, що ви можете зробити справжньою мовою програмування.