Проверка того, является ли stdin файлом или каналом или tty

#bash #shell #zsh

#bash #оболочка #zsh

Вопрос:

Я знаю, что для bash и zsh можно использовать, например [ -t 1 ] , для определения, является ли STDIN интерактивным сеансом tty.

Однако, похоже, нет способа проверить, перенаправляется ли stdin из файла или передается из команды:

 foo < ./file
bar | foo 
 

Есть ли какой-либо способ определить разницу между этими двумя? Отдельно, есть ли какой-либо способ получить путь к перенаправляемому файлу (за пределами /proc/self, который недоступен в macOS)?

Комментарии:

1. Какого ответа вы ожидаете, если ./file является именованным каналом?

Ответ №1:

Вы можете проверить, является ли /dev/stdin это обычным файлом или каналом:

 $ cat tmp.sh
#!/bin/bash

if [ -f /dev/stdin ]; then
    echo "file"
elif [ -p /dev/stdin ]; then
    echo "pipe"
fi
$ bash tmp.sh < foo.txt
file
$ echo foo | bash tmp.sh
pipe
 

Однако это зависит от /dev/stdin наличия в вашей файловой системе.

Вы также можете использовать stat команду, которая вернет информацию о стандартном вводе без указания аргумента имени файла. Как вы упомянули, что используете macOS, вы можете использовать %HT формат:

 $ stat -f %HT
Character Device
$ stat -f %HT < foo.txt
Regular File
$ echo foo | stat -f %HT
Fifo File
 

Комментарии:

1. «Bash обрабатывает несколько имен файлов, особенно когда они используются при перенаправлениях», включая /dev/stdin

2. -f /dev/stdin однако это не перенаправление.