Przekierowanie stderr w podpowłoce zmienia wyjście tput

3

Pracuję nad skryptem i znalazłem dziwne zachowanie. Jestem pewien, że istnieje logiczne wytłumaczenie, dlaczego wyjście 4 -go i 6 -go wiersza poleceń jest inna niż w innych przypadkach, ale nie udało mi się go znaleźć.

1 $ tput cols
128

2 $ tput cols 2>/dev/null
128

3 $ echo $(tput cols)
128

4 $ echo $(tput cols 2>/dev/null)
80

5 $ (tput cols >/tmp/cols.txt); cat /tmp/cols.txt
128

6 $ (tput cols &>/tmp/cols.txt); cat /tmp/cols.txt
80

7 $ echo $(tput cols 2>/dev/null; echo $COLUMNS; tput cols)
80 128 128

Dlaczego przekierowanie stderr zmienia wyjście tput w podpowłoce?

Ostatecznie chcę zrobić coś takiego w moim skrypcie, aby działał na systemach, w których tput / ncurses nie jest dostępny:

cols=$(tput cols 2>/dev/null || echo $COLUMNS)

Powyższy przykład został stworzony przy użyciu wersji Bash 4.3.46 (1) i ncurses 6.0.20150627

816–8055
źródło
Nie mam tego na rapsberry, jednak liczba kolumn może być inna, gdy dane wyjściowe nie są interaktywne (jak plik lub / dev / null)
Archemar

Odpowiedzi:

2

Zgodnie z stracetym dzieje się tak, ponieważ tputpróbuje tylko odczytać ustawienia tty z jego stdout i stderr (fd 1 i 2). Ponieważ wyraźnie przekierowałeś stderr, a $( )także przekierowuje stdout, tput się poddaje.

Najlepszym rozwiązaniem byłoby załatanie tput, aby sprawdzić także stdin na obecność tty; możesz jednak po prostu usunąć 2>/dev/nullprzekierowanie, ponieważ i tak tput colsnigdy nie wyświetla żadnych komunikatów o błędach. (A jeśli wygenerował jakieś komunikaty o błędach, najlepiej jest na nie zwrócić uwagę.)

grawitacja
źródło
Tak, to może być to. Muszę ukryć błąd, jeśli tput nie jest dostępny. Aby obejść ten problem, robię to: if tput cols &> / dev / null; następnie cols = $ (tput cols) else cols = $ COLUMNS fi
816-8055