Вопрос или проблема
Простая ситуация: я ищу wsdl
файл, потерянный в середине проекта.
$ find -name '*.wsdl'
./some/very/very/long/way/to/some/lost/directory/filename.wsdl
Теперь, когда я знаю, где он находится, я хочу что-то сделать с этим файлом, скажем, отредактировать его. Вместо того чтобы копировать/вставлять путь после моей команды, возможно ли использовать путь, возвращенный find
раньше? Так же, как можно получить доступ к последнему аргументу, который вы ввели с помощью !$
или к последней команде с !!
.
Я прочитал, что это возможно с $?
, но это только возвращает мне ошибку: 0: команда не найдена
$ echo $?
0: команда не найдена
Нет специальной переменной в bash для этого.
$?
содержит код завершения последней команды (0 = успех, >0 = код-ошибки)
Вы можете использовать вывод find
с флагом -exec
, вот так:
find -name '*.wsdl' -exec emacs {} \;
{}
заменяется именем файла, найденного find
. Это выполнит команду для каждого найденного файла. Если вы хотите выполнить команду со всеми найденными файлами как аргументами, используйте +
в конце вот так:
find -name '*.wsdl' -exec emacs {} +
Это откроет один экземпляр emacs с открытыми в нем всеми найденными файлами .wsdl.
Более общее решение – сохранить вывод в переменной:
result=$(find -name '*.wsdl')
emacs $result
Это работает со всеми командами, не только с find. Можно также использовать xargs
:
find -name '*.wsdl' | xargs emacs {}
Вот быстрый прием, который должен сделать то, что вы хотите, с минимальным количеством нажатий клавиш, если вы не против, что последняя команда будет выполнена дважды.
Используйте обратную кавычку:
`!!`
например:
$ find . -name HardToFind.txt some/crazy/path/to/HardToFind.txt $ vim `!!`
*редактировать: я вижу, что выше приведенный вопрос “возможно дублируемый” также содержит этот ответ. все еще актуально напрямую для данного вопроса, поэтому оставляю его, но извините за дубликат.
Запустите команду в подстановке команды:
output=$(find -name '*.wsdl')
Вывод теперь сохранен в переменной output
, которую вы можете использовать сколько угодно раз со следующей командой:
echo "$output"
`!!`
– отличное решение, но если вы хотите быть еще быстрее, можно использовать алиасы.
К сожалению, это не сработает:
~$ alias test="echo `!!`"
~$ test
zsh: команда не найдена: !!
Поэтому используйте `fc -e -`
Примеры алиасов, которые я использую:
копировать вывод:
alias co='echo `fc -e -` | xclip -in -selection clipboard'
открыть с помощью vim; если вывод имеет много строк, открывает все из них на вкладках:
alias vo='vim -p `fc -e -`'
Вы можете просто сделать `echo !!`
, и это вернет последнюю выполненную команду и ее вывод, хотя это выполнит команду снова.
$ pwd
/home/xoein
и вывод будет
$ `echo !!`
`echo pwd`
/home/xoein
Ответ или решение
Вопрос о том, как получить доступ к последнему возвращаемому значению в Bash, затрагивает часто возникающую задачу автоматизации и облегчения работы в терминале. При работе в командной оболочке Bash пользователи нередко сталкиваются с необходимостью повторно использовать результаты предыдущих команд. В этом контексте вопрос простоящий, но требует детального объяснения.
Теоретическая часть
Bash предоставляет несколько специальных механизмов для работы с командами и их выводом. Однако важно понимать, что $?
не подходит для наших целей, так как это псевдопеременная хранит только код завершения последней команды, а не её вывод. В нашем случае $?
вернет 0
при успешном выполнении команды, но это не соответствует содержимому файла или пути, который мы ищем.
С другой стороны, в Bash существует целый арсенал инструментов, которые позволяют обращаться к выводу прошлых команд. Команды вида !!
или !$
дают возможность работать с последней введенной командой и ее последним аргументом соответственно, но и они иногда могут не оправдать ожиданий, если требуется именно вывод команды, а не её синтаксис.
Пример практического применения
Возьмем ситуацию, когда вы с помощью команды find
нашли файл с определенным расширением, например, .wsdl
. И теперь вы хотите открыть этот файл в текстовом редакторе, но без необходимости копирования пути вручную.
find -name '*.wsdl'
# выводит: ./some/very/very/long/way/to/some/lost/directory/filename.wsdl
Чтобы не вводить длинный путь вручную, можно использовать несколько подходов. Один из таких подходов — использование подстановки команд с результатами.
Подстановка команд
emacs "$(find -name '*.wsdl')"
Этим подходом содержимое команды find
будет вставлено туда, где командная подстановка заключена в двойные кавычки. Таким образом, emacs
будет открыт с найденным файлом, путь к которому был определен предыдущей командой.
Альтернативные решения
Использование команды -exec
find -name '*.wsdl' -exec emacs {} \;
В этом примере команда -exec
позволяет непосредственно выполнить emacs
для каждого найденного .wsdl
файла. Это особенно полезно, если файлов несколько.
Применение xargs
Другой полезный инструмент — xargs
, который может последовательно передать вывод одной команды в другую.
find -name '*.wsdl' | xargs emacs
Этот подход очень близок к использованию -exec
, но более универсален, так как xargs
можно применять ко многим другим командам и сценариям.
Использование переменных
Также возможно предварительно сохранить вывод в переменной и затем использовать её:
result=$(find -name '*.wsdl')
emacs "$result"
Это дает гибкость на случай, если тот же вывод понадобится в разных частях скрипта.
Использование обратных кавычек
Иногда можно также использовать конструкцию с обратными кавычками, но важно помнить, что такое решение ведет к повторному выполнению команды:
vim `!!`
Заключение
Хотя использование изменения командной оболочки Bash для таких задач может показаться обходимым, понимание использования таких конструкций значительно упрощает повторяющиеся задачи в скриптах и командной строке, улучшая вашу эффективность и снижая вероятность ошибок. Такой подход не только ускоряет выполнение команд, но и улучшает доступ к передаче данных между различными компонентами в системе Linux. Умелое использование find
, xargs
и других средств становится бесценным навыком, особенно при управлении сложными проектами и множеством файлов.