Можно ли создать псевдоним для префикса команды для перенаправления stdout?

Вопрос или проблема

Извините за неинформативный заголовок…

Что я ищу, так это нечто, что позволит мне сократить перенаправление stdout.
Я знаю, что выполнение команды с пробелами перед ней не записывает её в историю, и есть несколько “волшебных” операторов, таких как “!!” и т.д.

В основном я ищу что-то подобное, что позволит мне заменить >/dev/null, чтобы я мог писать, например

git pull !!! и это было бы эквивалентно git pull>/dev/null

Существует ли что-то подобное? Могу ли я переопределить существующий оператор / написать новый?

Расширение псевдонимов проверяет только первый токен / слово строки, поэтому git pull !!! не может быть заменён расширением псевдонима.

Тем не менее, перенаправления работают даже если размещены перед командой, так что вы можете сделать это с помощью псевдонима:

alias quiet=">/dev/null "

Оставление пробела в конце расширения псевдонима заставляет bash рассматривать следующий токен для расширения псевдонима. (Вот почему обычно делают alias sudo='sudo '). Таким образом, это даже не нарушит ваши псевдонимы. Пример:

$ ll *.s xyz
ls: не удается получить доступ к 'xyz': Нет такого файла или каталога
-rw-r--r-- 1 peter peter 12 Mar  6 20:15 a64.s
-rw-r--r-- 1 peter peter 72 Mar  6 21:03 arm.s
-rw-r--r-- 1 peter peter 30 Mar 15 17:38 foo.s
-rw-r--r-- 1 peter peter 42 Mar  6 13:12 mips.s
$ quiet ll *.s xyz     # ll успешно развернут псевдоним, stdout отвергнут
ls: не удается получить доступ к 'xyz': Нет такого файла или каталога
$                      # stderr не перенаправлен.

Я бы использовал функцию

quietly() {
    # выполнить оставшиеся аргументы как команду, но перенаправить вывод
    "$@" > /dev/null
}

quietly git pull

Или функцию, которая считывает stdin и отвергает его:

q() { cat > /dev/null; }

git pull | q

Ни одно из этих решений не перенаправляет stderr: если что-то пойдет не так, вы должны об этом знать.

Псевдонимы возможны, как указывает ответ Питера Кордеса. Другой подход — это установка переменной окружения. Это позволяет использовать более естественный синтаксис перенаправления:

export d0='/dev/null'

которую вы затем можете использовать как

git pull >$d0

Это возможно, да, но не через псевдонимы – вместо этого с помощью функции extdebug в bash, которая позволяет вносить произвольные изменения в команду перед её выполнением (путем подавления оригинальной команды и eval нового).

shopt -s extdebug
trap "код здесь" DEBUG

Обработчик trap получит оригинальный ввод в $BASH_COMMAND, и возврат 1 из обработчика отменит оригинальную команду. Если ввести несколько команд, разделённых ;, trap вызывается отдельно для каждой.

Конкретно:

shopt -s extdebug
trap 'if [[ $BASH_COMMAND == *!!!* ]]; then
          eval "${BASH_COMMAND//!!!/"> /dev/null"}"; false
      fi' DEBUG

Это заменит любое !!! на > /dev/null в любом месте команды. Вы больше не сможете ввести echo 'Hi!!!'.

Если вы предпочитаете совпадать только в конце команды, это тоже легко сделать.

trap 'if [[ $BASH_COMMAND == *\ quietly ]]; then
          eval "${BASH_COMMAND% quietly} > /dev/null"; false
      fi' DEBUG

В качестве другого примера вы можете использовать это, чтобы сделать псевдоним command please для sudo command:

trap 'case $BASH_COMMAND in *\ please) eval sudo ${BASH_COMMAND% *}; false; esac' DEBUG

Существует другой способ добиться подобного: вы можете переопределить клавиши в Bash (readline) с помощью bind или ~/.inputrc, который также можно использовать для переопределения последовательностей клавиш.

Например, запись inputrc "!!!": "> /dev/null" или эквивалентная shell-команда bind '"!!!": "> /dev/null"' приведёт к тому, что текст > /dev/null будет вставляться каждый раз, когда вы попытаетесь ввести !!!.

Обратите внимание, что Bash не может предсказать будущее, что означает, что если вы хотите ввести единственный !, будет небольшая задержка перед его появлением – это Bash ждёт, чтобы увидеть, совпадёт ли это с последовательностью. Это может быть раздражающим, поэтому не привязывайте буквы и прочее.

На самом деле, было бы лучше привязать горячую клавишу Ctrl или Alt. Например, вы можете создать горячую клавишу Alt+Q с помощью "\eq": "> /dev/null".

Ранее: https://superuser.com/a/1459211

Ответ или решение

Да, это возможно, однако существуют определенные ограничения, касающиеся использования алиасов для переадресации stdout в Bash. В данном ответе я постараюсь изложить наиболее эффективные способы реализации такой переадресации, а также объяснить некоторые нюансы.

1. Использование алиаса для переадресации stdout

Как вы уже отметили, алиасы в Bash могут быть полезны для сокращения ввода команд. Однако важно понимать, что алиас расширяется только для первого слова в строке. Это означает, что команда, подобная git pull !!!, не может быть заменена с помощью алиаса.

Тем не менее, вы можете создать алиас, который включает в себя переадресацию stdout:

alias quiet=">/dev/null "

Добавление пробела в конце алиаса позволяет Bash обработать следующий токен как алиас. Таким образом, это решение также сохранит работоспособность других алиасов:

$ quiet ll *.s xyz  # aliased command executed successfully, stdout discarded

2. Использование функции

Если вам нужно более гибкое и мощное решение, я рекомендую использовать функции Bash. Например, можно создать функцию, которая переадресует вывод STDOUT в /dev/null:

quietly() {
    "$@" >/dev/null
}

quietly git pull

Эта функция берет любые переданные параметры и выполняет соответствующую команду, включая переадресацию вывода.

3. Чтение из stdin и его игнорирование

Если вы хотите игнорировать ввод, вы можете использовать следующую функцию:

q() { cat > /dev/null; }

git pull | q

Такой подход также может быть полезен, однако он не переадресовывает stderr, что может быть критично при возникновении ошибок.

4. Использование переменной среды

Еще один подход к этому вопросу — использование переменной среды, что может сделать синтаксис команды более естественным:

export d0='/dev/null'

После этого вы можете использовать:

git pull >$d0

5. Расширенные возможности с использованием trap

Bash предоставляет возможность модификации команд с помощью функции extdebug и trap, что может быть также полезно:

shopt -s extdebug
trap 'if [[ $BASH_COMMAND == *!!!* ]]; then eval "${BASH_COMMAND//!!!/> /dev/null}"; false; fi' DEBUG

Это позволит вам заменять в командах !!! на >/dev/null.

6. Настройка клавиш в Bash

Дополнительно, вы можете заново определить клавиши в Bash (readline), чтобы добавить возможность быстро вставлять >/dev/null:

bind '"!!!": ">/dev/null"'

Этот способ обеспечит авто-вставку, когда вы вводите определенные последовательности.

Заключение

Хотя Bash не предоставляет нативную возможность для написания алиасов, которые непосредственно переадресовывали бы stdout, существует несколько обходных путей, позволяющих достичь желаемой функциональности. Выбор способа зависит от ваших потребностей и предпочтений. Если вам нужна гибкость и мощность, рассмотрите возможность использования функций или системы trap. Если вы предпочитаете простоту, алиасы и переменные среды могут хорошо справляться с задачей.

Оцените материал
Добавить комментарий

Капча загружается...