Я пытаюсь написать небольшой скрипт, чтобы изменить текущий каталог на каталог моего проекта:
#!/bin/bash
cd /home/tree/projects/java
Я сохранил этот файл как proj, добавил разрешение на выполнение с chmod и скопировал его на /usr/bin. Когда я называю это:
proj, ничего не делает. Что я делаю не так?
В дальнейшем вы всегда можете попробовать протестировать его с помощью pwd в последней строке. Итак, перед завершением скрипта вы можете проверить, работает он или нет ..
@lesmana, как это дубликат?
@aland Поскольку OP действительно запускает сценарий нет, рабочий каталог для него не меняется. Команда cd хорошо работает внутри скриптов, попробуйте сами.
xdotool type --clearmodifiers 'cd ~/projects/java' && xdotool key KP_EnterПо сути это дубликат stackoverflow.com/questions/1464253/…





Сценарии оболочки запускаются внутри подоболочки, и каждая подоболочка имеет собственное представление о текущем каталоге. cd преуспевает, но как только подоболочка закрывается, вы снова в интерактивной оболочке, и там ничего не менялось.
Один из способов обойти это - использовать вместо этого псевдоним:
alias proj = "cd /home/tree/projects/java"
Псевдонимы не так гибки для управления или изменения. В случае большого количества компакт-дисков сценарии могут быть лучше.
Функции более гибкие, чем псевдонимы, поэтому, когда псевдонимов недостаточно, вам следует искать дальше.
Я думаю, что это обсуждение теряет смысл. «Есть миллионы способов делать что-то на Perl» (tm)
+1 за отличное объяснение вкупе с полезной альтернативой!
Стоит ли отмечать, что в MS-DOS поведение сценариев было таким, что вызываемый сценарий мог изменить каталог (и даже диск) вызывающей командной оболочки? А что в Unix этого дефекта нет?
Джонатан: хотя это правда, на самом деле это не связано с вопросом. Ответы на SO были бы вдвое длиннее, если бы каждый из них перечислял соответствующие недостатки MS-DOS!
s / дефект / побочный эффект /; s / стоит отметить / not & /
@ FedericoA.Ramponi или в ~ / .bash_aliases
Другой способ обойти это - загрузить файл сценария: . my-script или source my-script.
Вы не делаете ничего плохого! Вы изменили каталог, но только в подоболочке, в которой выполняется сценарий.
Вы можете запустить сценарий в текущем процессе с помощью команды «точка»:
. proj
Но я бы предпочел, чтобы предложение Грега использовать псевдоним в этом простом случае.
. также пишется как source, выберите тот, который вам больше запомнился.
@Ephemient: Хороший источник очков. Это объясняет, почему это рабочий источник. Также доказывает, что лень, а не необходимость, часто является источником изобретения.
@ephemient: обратите внимание, что исходный код используется в оболочке C и Bash; он не поддерживается ни в POSIX, ни в оболочках Korn, ни в классической оболочке Bourne.
"источник" используется в Z-оболочке
@AdamLiss Отлично работает, но есть один недостаток - каким-то образом команда source / dot отключает возможность автозавершения имени скрипта / команды клавишей TAB. По-прежнему можно добавлять аргументы / ввод с помощью клавиши TAB, но, к сожалению, имя команды необходимо вводить напрямую. Вы знаете, как заставить работать клавишу TAB в этом случае?
@Rafal Я тестировал это в своей системе (с терминала PuTTY). Я смог заполнить имя команды табуляцией без проблем как для точки, так и для «источника». Может быть, ваше окружение?
@ Стюарт. Ты прав. Я только что протестировал это на Ubuntu 14.04, и завершение табуляции отлично работает. Вероятно, это была проблема с Ubuntu 13.10 еще в январе 2014 года или, может быть, с моей конфигурацией. Спасибо за информацию.
Когда вы запускаете сценарий оболочки, он запускает экземпляр новый этой оболочки (/bin/bash). Таким образом, ваш скрипт просто запускает оболочку, меняет каталог и завершает работу. Другими словами, cd (и другие подобные команды) в сценарии оболочки не влияют и не имеют доступа к оболочке, из которой они были запущены.
Он изменяет только каталог для самого скрипта, в то время как ваш текущий каталог остается прежним.
Вместо этого вы можете использовать символическая ссылка. Он позволяет вам создать «ярлык» для файла или каталога, поэтому вам нужно будет только ввести что-то вроде cd my-project.
Наличие этой символической ссылки в каждом каталоге было бы неприятностью. Можно было бы поместить символическую ссылку в $ HOME, а затем выполнить cd ~ / my-project. Честно говоря, CDPATH проще использовать.
Вы можете сделать следующее:
#!/bin/bash
cd /your/project/directory
# start another shell and replacing the current
exec /bin/bash
Обновлено: это также может быть «пунктирным», чтобы предотвратить создание последующих оболочек.
Пример:
. ./previous_script (with or without the first line)
Это становится довольно беспорядочным после нескольких запусков .. Вам придется несколько раз нажать exit (или ctrl + d), чтобы выйти, например, из оболочки. Псевдоним намного чище (даже если команда оболочки выводит каталог, и он cd к выходу - alias something = "cd getnewdirectory.sh")
Обратите внимание на «exec». Заменяет старую оболочку.
Команда exec заменяет только вспомогательную оболочку, которая выполняла команду cd, но не оболочку, которая запускала сценарий. Если бы вы расставили точки в сценарии, то были бы правы.
Сделайте это «пунктирным» - без проблем. Я только что предложил решение. Это не зависит от того, как вы это запустите.
Хе-хе, я думаю, что лучше просто расставить однострочный скрипт точкой с помощью одной команды cd :) Я все равно сохраню свой ответ ... Это будет правильный глупый ответ на неправильный глупый вопрос :)
exec / bin / bash сделал то, что мне нужно. Спасибо!
Это помогло мне решить нерешенную проблему loong. Большое спасибо.
Идея Джереми Рутена об использовании символической ссылки вызвала мысль, которая не пересекалась ни с одним другим ответом. Использовать:
CDPATH=:$HOME/projects
Ведущая толстая кишка важна; это означает, что если в текущем каталоге есть каталог «dir», то «cd dir» изменится на него, а не перейдет в другое место. Установив значение, как показано, вы можете:
cd java
и, если в текущем каталоге нет подкаталога с именем java, он приведет вас прямо к $ HOME / projects / java - без псевдонимов, без сценариев, без сомнительных исполняемых файлов или команд с точкой.
Мой $ HOME - это / Users / jleffler; мой $ CDPATH:
:/Users/jleffler:/Users/jleffler/mail:/Users/jleffler/src:/Users/jleffler/src/perl:/Users/jleffler/src/sqltools:/Users/jleffler/lib:/Users/jleffler/doc:/Users/jleffler/work
для быстрой навигации по каталогам есть $ CDPATH, cdargs и способы автоматического создания псевдонимов
http://jackndempsey.blogspot.com/2008/07/cdargs.html
http://muness.blogspot.com/2008/06/lazy-bash-cd-aliaes.html
https://web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-5827311.html
Вы можете комбинировать псевдоним и скрипт,
alias proj = "cd \`/usr/bin/proj !*\`"
при условии, что сценарий повторяет путь назначения. Обратите внимание, что это обратные кавычки вокруг имени скрипта.
Например, ваш сценарий может быть
#!/bin/bash
echo /home/askgelal/projects/java/$1
Преимущество этого метода состоит в том, что сценарий может принимать любое количество параметров командной строки и выдавать различные пункты назначения, вычисленные с помощью, возможно, сложной логики.
Почему? вы можете просто использовать: proj() { cd "/home/user/projects/java/$1"; } => proj "foo" (или, proj "foo bar" <=, если у вас есть пробелы) ... или даже (например): proj() { cd "/home/user/projects/java/$1"; shift; for d; do cd "$d"; done; } => proj a b c => делает cd в /home/user/projects/java/a/b/c
cd выполняется в оболочке сценария. Когда сценарий завершается, оболочка закрывается, и вы остаетесь в том же каталоге, в котором находились. "Исходный" сценарий, не запускайте его. Вместо:
./myscript.sh
делать
. ./myscript.sh
(Обратите внимание на точку и пробел перед именем сценария.)
Это круто и, наверное, полезно знать. Но что именно последний делает (как это работает)? Это, наверное, лучшее решение в этой теме.
fwiw, в разделе комментариев к ответу Адама Лисса ephemient отвечает на вопрос о том, что это за '.' является. Это то же самое, что и source
Будьте осторожны, «источник» - это башизм. т.е. тире (Debian по умолчанию для / bin / sh) не поддерживает его, а "." работает как положено.
Отличный ответ! также, если myscript.sh находится в каталоге, включенном в $ PATH, вы можете получить его откуда угодно, не указывая полный путь.
Это сработало для меня лучше всего. Это самое простое решение (+1).
Создайте файл сценария
#!/bin/sh # file : /scripts/cdjava # cd /home/askgelal/projects/java
Затем создайте псевдоним в файле запуска.
#!/bin/sh # file /scripts/mastercode.sh # alias cdjava='. /scripts/cdjava'
Например, создайте главный файл псевдонимов / функций: /scripts/mastercode.sh
(Поместите псевдоним в этот файл.)
Затем в конце вашего файла .bashrc:
source /scripts/mastercode.sh
Теперь легко перейти к cd в ваш каталог java, просто введите cdjava, и вы там.
файл mastercode.sh не нуждается в шабанге (#!/bin/sh), поскольку он не (и не может быть) выполнен в подоболочке. Но в то же время вам необходимо задокументировать "вкус" оболочки этого файла; например, ksh или bash (или (t) csh / zsh и т. д.), и почти наверняка это не sh. Я обычно добавляю комментарий (но не шебанг), чтобы сообщить об этом; например, «этот файл должен быть получен (из bash), а не запускаться как сценарий оболочки».
Еще один совет (для bash): если вы используете переменные в своем скрипте, то, поскольку скрипт является sourced (через alias), эти переменные попадут в среду вашей оболочки. Чтобы этого избежать, выполняйте всю работу сценария в функции и просто вызывайте ее в конце сценария. Внутри функции объявите любые переменные local.
в ubuntu просто создайте ~ / .bash_aliases (если он еще не существует). Затем просто добавьте туда свои псевдонимы, перезапустите терминал и готово.
Я сделал следующее:
создать файл с именем case
вставьте в файл следующее:
#!/bin/sh
cd /home/"$1"
сохраните его, а затем:
chmod +x case
Я также создал псевдоним в моем .bashrc:
alias disk='cd /home/; . case'
теперь, когда я печатаю:
case 12345
по сути я печатаю:
cd /home/12345
Вы можете ввести любую папку после case:
case 12
case 15
case 17
что похоже на ввод:
cd /home/12
cd /home/15
cd /home/17
соответственно
В моем случае путь намного длиннее - эти ребята резюмировали его с помощью информации ~ ранее.
cd в псевдониме лишний и неэлегантный; псевдоним должен просто '. ~ / case` вместо этого. Кроме того, case - это зарезервированное ключевое слово, поэтому это довольно плохой выбор для имени.
cd в вашем сценарии технически работал, поскольку он изменил каталог оболочки, в которой запускался сценарий, но это был отдельный процесс, разветвленный из вашей интерактивной оболочки.
Posix-совместимый способ решить эту проблему - определить процедура оболочки, а не командный сценарий, вызываемую оболочкой.
jhome () {
cd /home/tree/projects/java
}
Вы можете просто ввести это или вставить в один из различных файлов запуска оболочки.
Согласен, это лучший ответ, наткнулся. Кроме того, псевдоним может быть подходящим в некоторых ситуациях, но если он пытается использовать cd в сценарии и хочет добавить к нему что-нибудь еще, псевдоним будет бесполезен.
Это похоже на решение! И я пытаюсь реализовать его, но он не работает :( вот мой сценарий: #! / Bin / bash jhome () {echo "please" cd / home echo "work"} jhome
@GantMan, вы должны добавить это в "файлы запуска оболочки", например ~ / .bashrc
Если он находится в файле, вам нужно использовать . filename или source filename, чтобы текущая оболочка увидела его, а не подоболочку, которая выполнила команду. Или воспользуйтесь советом Джеки и вставьте что-нибудь вроде ~/.bashrc.
Вы также можете использовать аргумент (или два ...), например: jhome(){ cd /home/tree/projects/$1; }
Это должно быть правильным способом, это позволяет использовать специальные символы, такие как, например, «-».
Отлично, просто решил мою проблему безупречно. При этом следует отметить правильный ответ.
Вы можете комбинировать псевдонимы Адама и Грега и точечный подход, чтобы сделать что-то более динамичное -
alias project = ". project"
Теперь при запуске псевдонима проекта сценарий проекта будет выполняться в текущей оболочке, а не в подоболочке.
Это именно то, что мне нужно, чтобы поддерживать весь мой скрипт и просто вызывать его из bash и поддерживать текущий сеанс - это ИДЕАЛЬНЫЙ ответ.
В моем конкретном случае мне нужно было слишком много раз менять один и тот же каталог. Итак, на моем .bashrc (я использую ubuntu) я добавил
1 -
$ nano ~./bashrc
function switchp
{
cd /home/tree/projects/$1
}
2-
$ source ~/.bashrc
3 -
$ switchp java
Непосредственно это будет: cd / home / tree / projects / java
Надеюсь, это поможет!
@ W.M. В конечном итоге вы можете выполнить команду «$ switchp» без каких-либо параметров, чтобы перейти непосредственно к дереву проекта.
@workdreamer Функциональный подход, который вы описали выше, решил небольшую проблему при переходе в подпапки, которые имеют ту же родительскую папку в моей системе. Спасибо.
Я заставил свой код работать с помощью . <your file name>
Доза ./<your file name> не работает, потому что она не меняет ваш каталог в терминале, а просто меняет каталог, специфичный для этого сценария.
Вот моя программа
#!/bin/bash
echo "Taking you to eclipse's workspace."
cd /Developer/Java/workspace
Вот мой терминал
nova:~ Kael$
nova:~ Kael$ . workspace.sh
Taking you to eclipe's workspace.
nova:workspace Kael$
В чем разница между . something и ./something ?? Этот ответ сработал для меня, и я не понимаю, почему.
. something позволяет запускать сценарий из любого места, ./something требует, чтобы вы находились в каталоге, в котором хранится файл.
@Dracorat stackoverflow.com/questions/13786499/…
Вы можете поставить точку в строке shebang? #!. /bin/bash?
Если вы используете рыбы в качестве оболочки, лучшим решением будет создание функции. В качестве примера, учитывая исходный вопрос, вы можете скопировать 4 строки ниже и вставить их в командную строку fish:
function proj
cd /home/tree/projects/java
end
funcsave proj
Это создаст функцию и сохранит ее для дальнейшего использования. Если ваш проект изменится, просто повторите процесс, используя новый путь.
При желании вы можете вручную добавить файл функции, выполнив следующие действия:
nano ~/.config/fish/functions/proj.fish
и введите текст:
function proj
cd /home/tree/projects/java
end
и, наконец, нажмите ctrl + x для выхода и y, а затем return, чтобы сохранить изменения.
(ПРИМЕЧАНИЕ: первый метод использования funcsave создает для вас файл proj.fish.).
Вы можете использовать оператор &&:
cd myDirectory && ls
Голос против: это не попытка ответить на актуальный вопрос здесь. Вы можете запустить две команды в командной строке (с &&, если вы хотите, чтобы вторая была условной для первой, или просто с ; или новой строкой между ними), но вставка этого в сценарий вернет вас к вопросу «почему не родительский оболочки использовать новый каталог, когда cd действительно был успешным? "
Вы можете выполнить несколько строк в той же подоболочке, если закончите строки обратной косой чертой.
cd somedir; \
pwd
В вашем файле ~ / .bash_profile. добавить следующую функцию
move_me() {
cd ~/path/to/dest
}
Перезагрузите терминал, и вы можете ввести
move_me
и вы будете перемещены в папку назначения.
У меня есть простой сценарий bash под названием p для управления изменением каталога на
github.com/godzilla/bash-stuff
просто поместите скрипт в локальный каталог bin (/ usr / local / bin)
и ставим
alias p='. p'
в вашем .bashrc
что это делает? похоже, что он будет рекурсивно запускаться сам, хотя я уверен, что если вы запускали его раньше, он этого не сделает;)
Хотя поиск сценария, который вы хотите запустить, является одним из решений, вы должны знать, что этот сценарий затем может напрямую изменять среду вашей текущей оболочки. Также больше нельзя передавать аргументы.
Другой способ - реализовать ваш скрипт как функцию в bash.
function cdbm() {
cd whereever_you_want_to_go
echo "Arguments to the functions were $1, $2, ..."
}
Этот метод используется функцией autojump: http://github.com/joelthelion/autojump/wiki, чтобы предоставить вам обучающие закладки каталога оболочки.
Вы можете использовать . для выполнения сценария в текущей среде оболочки:
. script_name
или, альтернативно, его более читаемый, но специфичный для оболочки псевдоним source:
source script_name
Это позволяет избежать подоболочки и позволяет любым переменным или встроенным функциям (включая cd) вместо этого влиять на текущую оболочку.
exec bash в концеA bash script operates on its current environment or on that of its children, but never on its parent environment.
Однако этот вопрос часто задают, потому что нужно оставаться в (новом) приглашении bash в определенном каталоге после выполнения сценария bash из другого каталога.
Если это так, просто выполнить дочерний экземпляр bash в конце скрипта:
#!/usr/bin/env bash
cd /home/tree/projects/java
echo -e '\nHit [Ctrl]+[D] to exit this child shell.'
exec bash
Чтобы вернуться к предыдущему родительскому экземпляру bash, используйте Ctrl + D.
По крайней мере, с более новыми версиями bash, exec в последней строке больше не требуется. Более того, сценарий можно заставить работать с любой предпочтительной оболочкой, используя переменную среды $SHELL. Тогда это дает:
#!/usr/bin/env bash
cd desired/directory
echo -e '\nHit [Ctrl]+[D] to exit this child shell.'
$SHELL
Это создает новую подоболочку. Когда вы наберете exit, вы вернетесь в оболочку, в которой вы запускали этот скрипт.
Когда скрипт вызывается несколько раз, кажется, что он создает вложенные оболочки, и мне нужно много раз вводить «выход». Можно ли это как-то решить?
См. Другие ответы: используйте псевдоним, используйте "pushd / popd / dirs" или используйте "source"
@Acumenus Вы совершенно правы. exec требовался со старыми версиями bash и, возможно, другими оболочками. Я обновил ответ соответственно.
Могу ли я после запуска exec bash оставаться в сценарии и продолжать выполнять другие команды?
@alper Да, конечно. В новом дочернем экземпляре bash можно выполнить больше команд. Чтобы вернуться к предыдущему родительскому экземпляру bash, используйте [Ctrl] + [D].
Вы можете создать в вашем .bash_profile функцию, как показано ниже, и она будет работать без сбоев.
Следующая функция принимает необязательный параметр - проект. Например, вы можете просто запустить
cdproj
или же
cdproj project_name
Вот определение функции.
cdproj(){
dir=/Users/yourname/projects
if [ "$1" ]; then
cd "${dir}/${1}"
else
cd "${dir}"
fi
}
Не забудьте указать источник вашего .bash_profile
Вам не нужен скрипт, только установите правильный параметр и создайте переменную среды.
shopt -s cdable_vars
в вашем ~/.bashrc позволяет cd содержимое переменных среды.
Создайте такую переменную окружения:
export myjava = "/home/tree/projects/java"
и вы можете использовать:
cd myjava
просто запустите:
cd /home/xxx/yyy && command_you_want
Как объяснялось в других ответах, вы изменили каталог, но только в суб-оболочка, которая запускает скрипт. это не влияет на родительскую оболочку.
Одно из решений - использовать функции bash вместо сценария bash (sh); поместив код сценария bash в функцию. Это делает функцию доступной как команду, а затем она будет выполняться без дочернего процесса, и, таким образом, любая команда cd повлияет на оболочку вызывающего.
Функции Bash:
Одной из функций профиля bash является хранение пользовательских функций, которые можно запускать в терминале или в сценариях bash так же, как вы запускаете приложение / команды, это также можно использовать как ярлык для длинных команд.
Чтобы ваша система работала эффективно, вам нужно будет скопировать вашу функцию в конец нескольких файлов.
/home/user/.bashrc
/home/user/.bash_profile
/root/.bashrc
/root/.bash_profile
Вы можете sudo kwrite /home/user/.bashrc /home/user/.bash_profile /root/.bashrc /root/.bash_profile для быстрого редактирования / создания этих файлов
Как :
Скопируйте код сценария bash в новую функцию в конце файла профиля bash и перезапустите терминал, затем вы можете запустить cdd или любую другую функцию, которую вы написали.
Пример сценария
Делаем ярлык на cd .. с cdd
cdd() {
cd ..
}
ls ярлык
ll() {
ls -l -h
}
ls ярлык
lll() {
ls -l -h -a
}
Это действительно работает. Я удивлен, что за него не проголосовали так, как он того заслуживает.
@EerikSvenPuudist :) это был поздний ответ на популярный пост, я думаю, читатели не дойдут до него, спасибо за голос
Это должно делать то, что вы хотите. Перейдите в интересующий каталог (из сценария), а затем создайте новую оболочку bash.
#!/bin/bash
# saved as mov_dir.sh
cd ~/mt/v3/rt_linux-rt-tools/
bash
Если вы запустите это, он перенесет вас в интересующий каталог, а когда вы выйдете из него, он вернет вас в исходное место.
root@intel-corei7-64:~# ./mov_dir.sh
root@intel-corei7-64:~/mt/v3/rt_linux-rt-tools# exit
root@intel-corei7-64:~#
Это даже вернет вас обратно в исходный каталог при выходе (CTRL + d)
Создание нового bash будет означать, что вы потеряете свою историю, и она начнется заново.
Обратите внимание на обсуждение Как установить рабочий каталог родительского процесса?
Он содержит несколько хакерских ответов, например
https://stackoverflow.com/a/2375174/755804 (изменение каталога родительского процесса через gdb, не делайте этого) и https://stackoverflow.com/a/51985735/755804 (команда tailcd, которая вводит cd dirname во входной поток родительского процесса; в идеале она должна быть частью bash, а не взломом)
Это старый вопрос, но я очень удивлен, что не вижу здесь этого трюка.
Вместо использования компакт диск вы можете использовать
export PWD=the/path/you/want
Нет необходимости создавать подоболочки или использовать псевдонимы.
Обратите внимание, что вы обязаны убедиться, что / path / you / want существует.
Мне нужно работать в tcsh, и я знаю, что это не изящное решение, но, например, если бы мне пришлось изменить папки на путь, в котором одно слово отличается, все это можно сделать в псевдониме
a alias_name 'set a = `pwd`; set b = `echo $a | replace "Trees" "Tests"` ; cd $b'
Если путь всегда фиксирован, справедливо
a alias_name2 'cd path/you/always/need'
должно сработать В строке выше установлен новый путь к папке
Это объединяет ответ Сергея с несвязанный ответ Дэвида. Он меняет каталог, а затем вместо принудительной установки оболочки bash использует запускает оболочку пользователя по умолчанию. Однако для определения оболочки по умолчанию требуются как getent, так и /etc/passwd.
#!/usr/bin/env bash
cd desired/directory
USER_SHELL=$(getent passwd <USER> | cut -d : -f 7)
$USER_SHELL
Конечно, это все тот же недостаток создания вложенной оболочки.
межсайтовый дубликат: superuser.com/questions/176783/…