Тому що це особливість оболонки (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 не може зробити. Це все ще набагато обмежено, ніж те, що ви можете зробити справжньою мовою програмування.