Я хотел бы иметь возможность использовать результат последней выполненной команды в следующей команде. Например,
$ find . -name foo.txt
./home/user/some/directory/foo.txt
Теперь предположим, что я хочу иметь возможность открыть файл в редакторе, или удалить его, или сделать с ним что-нибудь еще, например
mv <some-variable-that-contains-the-result> /some/new/location
Как я могу это сделать? Может быть, использовать какую-то переменную bash?
Обновить:
Чтобы уточнить, я не хочу назначать вещи вручную. Мне нужно что-то вроде встроенных переменных bash, например
ls /tmp
cd $_
$_
содержит последний аргумент предыдущей команды. Я хочу нечто подобное, но с выводом последней команды.
Окончательное обновление:
Ответ Сета сработал довольно хорошо. Следует иметь в виду следующее:
- не забудьте,
touch /tmp/x
когда пробуете решение в первый раз - результат будет сохранен только в том случае, если код выхода последней команды был успешным
linux
bash
command-line
Armandino
источник
источник
Ответы:
Это действительно хакерское решение, но, похоже, иногда оно работает. Во время тестирования я заметил, что иногда это не очень хорошо работает при получении ^Cв командной строке, хотя я немного подправил его, чтобы вести себя немного лучше.
Этот взлом предназначен только для интерактивного режима, и я совершенно уверен, что никому его не рекомендую. Фоновые команды могут вызвать еще менее определенное поведение, чем обычно. Другие ответы - лучший способ программного получения результатов.
При этом вот «решение»:
PROMPT_COMMAND='LAST="`cat /tmp/x`"; exec >/dev/tty; exec > >(tee /tmp/x)'
Установите эту переменную окружения bash и выдает нужные команды.
$LAST
обычно будет вывод, который вы ищете:startide seth> fortune Courtship to marriage, as a very witty prologue to a very dull play. -- William Congreve startide seth> echo "$LAST" Courtship to marriage, as a very witty prologue to a very dull play. -- William Congreve
источник
PROMPT_COMMAND='last="$(cat /tmp/last)";lasterr="$(cat /tmp/lasterr)"; exec >/dev/tty; exec > >(tee /tmp/last); exec 2>/dev/tty; exec 2> >(tee /tmp/lasterr)'
который предоставляет и$last
и$lasterr
.No such file or directory
2> >(tee /tmp/lasterr 1>&2)
потому что стандартный выводtee
должен быть перенаправлен обратно на стандартную ошибку.Я не знаю ни одной переменной, которая бы делала это автоматически . Чтобы сделать что-то помимо простого копирования и вставки результата, вы можете повторно запустить все, что вы только что сделали, например
Где
!!
расширение истории означает «предыдущая команда».Если вы ожидаете, что будет одно имя файла с пробелами или другими символами, которые могут помешать правильному синтаксическому анализу аргументов, укажите результат в кавычках (
vim "$(!!)"
). Если оставить его без кавычек, можно будет открывать сразу несколько файлов, если они не содержат пробелов или других токенов синтаксического анализа оболочки.источник
vim `!!`
date "+%N"
а затемecho $(!!)
Баш - некрасивый язык. Да, вы можете назначить вывод переменной
MY_VAR="$(find -name foo.txt)" echo "$MY_VAR"
Но лучше надейтесь, что из ваших усилийfind
вернется только один результат и что в этом результате не будет никаких «нечетных» символов, таких как возврат каретки или перевод строки, поскольку они будут незаметно изменены при присвоении переменной Bash.Но лучше будьте осторожны, чтобы правильно указывать вашу переменную при ее использовании!
Это лучше действовать на файл непосредственно, например , с
find
«s-execdir
(обратитесь к руководству).find -name foo.txt -execdir vim '{}' ';'
или
find -name foo.txt -execdir rename 's/\.txt$/.xml/' '{}' ';'
источник
echo "${MY_VAR}"
чтобы убедиться, что это так.Есть несколько способов сделать это. Один из способов - использовать,
v=$(command)
который назначит вывод командыv
. Например:v=$(date) echo $v
И вы также можете использовать обратные кавычки.
v=`date` echo $v
Из руководства для начинающих по Bash ,
EDIT: после редактирования вопроса кажется, что это не то, что ищет OP. Насколько мне известно, специальной переменной, как
$_
для вывода последней команды, нет.источник
Это довольно просто. Используйте обратные кавычки:
И тогда вы можете использовать это в любое время в будущем
echo $var mv $var /somewhere
источник
Дискламеры:
При запуске интерактивной оболочки в tmux вы можете легко получить доступ к данным, отображаемым в данный момент на терминале. Давайте посмотрим на несколько интересных команд:
Да, теперь это дает нам много возможностей :) Что касается меня, я установил простой псевдоним:
alias L="tmux capture-pane; tmux showb -b 0 | tail -n 3 | head -n 1"
и теперь каждый раз, когда мне нужно получить доступ к последней строке, я просто использую,$(L)
чтобы ее получить.Это не зависит от выходного потока, используемого программой (будь то stdin или stderr), метода печати (ncurses и т. Д.) И кода выхода программы - данные просто нужно отобразить.
источник
Я думаю, вы могли бы взломать решение, которое включает настройку вашей оболочки на скрипт, содержащий:
#!/bin/sh bash | tee /var/log/bash.out.log
Затем, если вы настроили
$PROMPT_COMMAND
вывод разделителя, вы можете написать вспомогательную функцию (возможно, вызываемую_
), которая получит последний фрагмент этого журнала, чтобы вы могли использовать его так:% find lots*of*files ... % echo "$(_)" ... # same output, but doesn't run the command again
источник
Вы можете настроить следующий псевдоним в своем профиле bash:
alias s='it=$($(history | tail -2 | head -1 | cut -d" " -f4-))'
Затем, набрав 's' после произвольной команды, вы можете сохранить результат в переменной оболочки 'it'.
Итак, пример использования:
$ which python /usr/bin/python $ s $ file $it /usr/bin/python: symbolic link to `python2.6'
источник
grab
функции, которая копирует n-ю строку из последней команды в буфер обмена gist.github.com/davidhq/f37ac87bc77f27c5027eЯ просто извлек эту
bash
функцию из предложенных здесь:grab() { grab=$("$@") echo $grab }
Затем вы просто делаете:
> grab date Do 16. Feb 13:05:04 CET 2012 > echo $grab Do 16. Feb 13:05:04 CET 2012
Обновление : анонимный пользователь предложил заменить
echo
,printf '%s\n'
что имеет то преимущество, что он не обрабатывает параметры, как-e
в захваченном тексте. Итак, если вы ожидаете или испытываете такие особенности, рассмотрите это предложение. Другой вариант - использоватьcat <<<$grab
вместо него.источник
cat <<<$grab
вариант?man bash
: «Here Strings: вариант здесь документов, формат следующий:<<<word
слово раскрывается и передается команде на ее стандартный ввод». Итак, значение$grab
передаетсяcat
на стандартный ввод иcat
просто возвращает его обратно на стандартный вывод.Говоря «Я хотел бы иметь возможность использовать результат последней выполненной команды в следующей команде», я предполагаю - вы имеете в виду результат любой команды, а не только поиск.
Если это так - xargs - это то, что вы ищете.
find . -name foo.txt -print0 | xargs -0 -I{} mv {} /some/new/location/{}
ИЛИ, если вы хотите сначала увидеть результат:
find . -name foo.txt -print0
!! | xargs -0 -I{} mv {} /some/new/location/{}
Эта команда работает с несколькими файлами и работает как шарм, даже если путь и / или имя файла содержат пробелы.
Обратите внимание на часть команды mv {} / some / new / location / {} . Эта команда создается и выполняется для каждой строки, напечатанной предыдущей командой. Здесь строка, напечатанная предыдущей командой, заменяется вместо {} .
Выдержка из справочной страницы xargs:
Подробнее см. Справочную страницу:
man xargs
источник
Захват вывода с обратными кавычками:
output=`program arguments` echo $output emacs $output
источник
Обычно я делаю то, что предлагают другие ... без задания:
$find . -iname '*.cpp' -print ./foo.cpp ./bar.cpp $vi `!!` 2 files to edit
Вы можете стать красивее, если хотите:
$grep -R "some variable" * | grep -v tags ./foo/bar/xxx ./bar/foo/yyy $vi `!!`
источник
Если все, что вам нужно, это повторно запустить вашу последнюю команду и получить результат, подойдет простая переменная bash:
Итак, вы можете запустить свою команду на выходе с помощью:
yourCommand $LAST
Это вызовет новый процесс и повторно выполнит вашу команду, а затем выдаст вам результат. Похоже, что вам действительно нужен файл истории bash для вывода команд. Это означает, что вам нужно будет захватить вывод, который bash отправляет на ваш терминал. Вы можете написать что-нибудь, чтобы следить за необходимостью / dev или / proc, но это беспорядочно. Вы также можете просто создать «специальный канал» между вашим термином и bash с помощью команды tee в середине, которая перенаправляет на ваш выходной файл.
Но оба это своего рода хакерские решения. Думаю, лучше всего будет терминатор - более современный терминал с логированием вывода. Просто проверьте свой файл журнала на предмет результатов последней команды. Переменная bash, подобная приведенной выше, сделает это еще проще.
источник
Вот один из способов сделать это после того, как вы выполнили свою команду и решили, что хотите сохранить результат в переменной:
$ find . -name foo.txt ./home/user/some/directory/foo.txt $ OUTPUT=`!!` $ echo $OUTPUT ./home/user/some/directory/foo.txt $ mv $OUTPUT somewhere/else/
Или, если вы заранее знаете, что хотите получить результат в переменной, вы можете использовать обратные кавычки:
$ OUTPUT=`find . -name foo.txt` $ echo $OUTPUT ./home/user/some/directory/foo.txt
источник
В качестве альтернативы существующим ответам: используйте,
while
если имена ваших файлов могут содержать такие пробелы:find . -name foo.txt | while IFS= read -r var; do echo "$var" done
Как я уже писал, разница актуальна только в том случае, если вам нужно ожидать пробелов в именах файлов.
NB: единственная встроенная информация не о выводе, а о статусе последней команды.
источник
вы можете использовать !!: 1. Пример:
источник
У меня была аналогичная потребность, в которой я хотел использовать вывод последней команды в следующей. Очень похоже на | (труба). например
$ which gradle /usr/bin/gradle $ ls -alrt /usr/bin/gradle
к чему-то вроде -
$ which gradle |: ls -altr {}
Решение: Создал эту кастомную трубу. Действительно просто, используя xargs -
$ alias :='xargs -I{}'
По сути, ничего, создавая короткую руку для xargs, это работает как шарм и действительно удобно. Я просто добавляю псевдоним в файл .bash_profile.
источник
Это можно сделать, используя магию файловых дескрипторов и
lastpipe
опцию оболочки.Это нужно делать с помощью скрипта - опция «lastpipe» не будет работать в интерактивном режиме.
Вот сценарий, который я тестировал:
$ cat shorttest.sh #!/bin/bash shopt -s lastpipe exit_tests() { EXITMSG="$(cat /proc/self/fd/0)" } ls /bloop 2>&1 | exit_tests echo "My output is \"$EXITMSG\"" $ bash shorttest.sh My output is "ls: cannot access '/bloop': No such file or directory"
Что я здесь делаю:
установка опции оболочки
shopt -s lastpipe
. Без этого он не будет работать, так как вы потеряете дескриптор файла.убедиться, что мой stderr также попадает в
2>&1
передача вывода в функцию, чтобы можно было ссылаться на дескриптор файла stdin.
установка переменной путем получения содержимого
/proc/self/fd/0
дескриптора файла, которым является stdin.Я использую это для фиксации ошибок в скрипте, поэтому, если есть проблема с командой, я могу остановить обработку скрипта и сразу выйти.
shopt -s lastpipe exit_tests() { MYSTUFF="$(cat /proc/self/fd/0)" BADLINE=$BASH_LINENO } error_msg () { echo -e "$0: line $BADLINE\n\t $MYSTUFF" exit 1 } ls /bloop 2>&1 | exit_tests ; [[ "${PIPESTATUS[0]}" == "0" ]] || error_msg
Таким образом, я могу добавить
2>&1 | exit_tests ; [[ "${PIPESTATUS[0]}" == "0" ]] || error_msg
каждую команду, которую хочу проверить.Теперь вы можете наслаждаться своим результатом!
источник
Это не строго решение bash, но вы можете использовать конвейер с sed, чтобы получить последнюю строку вывода предыдущих команд.
Сначала давайте посмотрим, что у меня в папке "а"
Затем ваш пример с ls и cd превратится в sed и piping примерно так:
rasjani@helruo-dhcp022206::~$ cd `find a |sed '$!d'` rasjani@helruo-dhcp022206::~/a/baz$ pwd /home/rasjani/a/baz rasjani@helruo-dhcp022206::~/a/baz$
Итак, настоящая магия происходит с sed: вы передаете результат любой команды в sed, а sed выводит последнюю строку, которую вы можете использовать в качестве параметра с обратными тиками. Или вы также можете объединить это с xargs. ("man xargs" в оболочке - ваш друг)
источник
В оболочке нет специальных символов, подобных Perl, которые хранят результат эха последней команды.
Научитесь использовать символ вертикальной черты с awk.
find . | awk '{ print "FILE:" $0 }'
В приведенном выше примере вы можете:
find . -name "foo.txt" | awk '{ print "mv "$0" ~/bar/" | "sh" }'
источник
еще один способ, хоть и грязный.
источник
Я считаю, что запоминание вывода моих команд в конкретный файл немного раздражает, мое решение - это функция,
.bash_profile
которая улавливает вывод в файле и возвращает результат, когда он вам нужен.Преимущество этого заключается в том, что вам не нужно повторно запускать всю команду (при использовании
find
или других длительных команд, которые могут быть критическими)Достаточно просто, вставьте это в свой
.bash_profile
:Сценарий
# catch stdin, pipe it to stdout and save to a file catch () { cat - | tee /tmp/catch.out} # print whatever output was saved to a file res () { cat /tmp/catch.out }
Применение
$ find . -name 'filename' | catch /path/to/filename $ res /path/to/filename
На этом этапе я обычно просто добавляю
| catch
все свои команды в конец, потому что это не требует затрат и избавляет меня от необходимости повторно запускать команды, выполнение которых требует много времени.Кроме того, если вы хотите открыть вывод файла в текстовом редакторе, вы можете сделать это:
# vim or whatever your favorite text editor is $ vim <(res)
источник