Скопировано изhttps://unix.stackexchange.com/a/88327
Предположим, что ваш /bin/sh
является POSIXsh
(на Solaris 10 и более ранних версиях, в котором вместо этого была оболочка Bourne, вместо этого используйте /usr/xpg4/bin/sh
):
if [ -t 0 ] && [ -t 1 ]; then
old_settings=$(stty -g) || exit
stty -icanon -echo min 0 time 3 || exit
printf '\033[6n'
pos=$(dd count=1 2> /dev/null)
pos=${pos%R*}
pos=${pos##*\[}
x=${pos##*;} y=${pos%%;*}
stty "$old_settings"
fi
Это предполагает, что весь ответ придет за один раз, ожидая его до 0,3 секунды. В целом это должно быть верно для эмуляторов терминала и устройств pty, но не обязательно для терминалов через последовательный порт. Вы можете изменить его на min 8 time 3
, чтобы продолжать ждать (до 0,3 секунды между каждым байтом ), пока не будут прочитаны 8 байтов, но с тем недостатком, что всегда будет занимать не менее 0,3 секунды, если ответ короче, чем 8 байт и зависнет навсегда, если не будет ответа ).
Вы можете использовать awk -F'[^0-9]+' -v RS=R '{print $3, $2; exit}'
с min 1 time 0
. Это будет работать с awk
реализациями, отличными от mawk
(, которые настаивают на накоплении буфера, полного данных на входе, прежде чем начинать их обработку ).
В конце концов, чтение по одному байту за раз, как вы делаете в своем собственном ответе, является наиболее надежным. Вы можете добавить тайм-аут для учета терминалов, которые не отправляют ответ.
Из zsh
снаряда:
print -rC1 -- /**/y/x(/D)
Глоб **
соответствует подкаталогам, а квалификатор (/D)
glob указывает, что результирующие пути должны быть каталогами и что шаблон также должен соответствовать скрытым именам (, как и dotglob
вbash
).
Или приблизительный эквивалент из bash
версии 4 или более поздней (, т. е. установленной из Homebrew на macOS, а не по умолчаниюbash
):
shopt -s globstar failglob dotglob
printf '%s\n' /**/y/x/
Параметр оболочки globstar
в bash
позволяет использовать шаблон подстановки **
, а failglob
приводит к сбою сопоставления шаблонов с ошибкой, если совпадений нет. Поведение failglob
используется по умолчанию в zsh
, как и доступность **
.
find
вероятно, будет быстрее:
find / -type d -path '*/y/x'
Это найдет любой каталог с именем x
, находящийся в каталоге с именем y
где-то под /
.
Или у вас может быть функциональная locate
утилита, с помощью которой вы можете
locate '*/y/x'
Это будет самый быстрый вариант, но он будет возвращать только результаты, доступные любому пользователю в системе, и может быть не совсем актуальным.