In tcsh, how to set bind-key for general command like cd or ps ?
I was trying bindkey "^G" "cd ../../" I get error Bad Command name: cd
I have looked at few online example. Its working when I want to do something, history search forward or end of line. But I want to do it for some other common command which I execute thousands of time in given day. e.g I use CD or ps command very often. I wanted to set bindkey for such commands ?
You can use the -c flag when setting bindkeys for external commands. For instance: bindkey -c "^]^d" "ls /" will bind Ctrl+]+d to spit out the contents of the root directory.
In your case:
bindkey -c "^G" 'cd ../../'
One caveat here is that your shell prompt may not update upon execution via the bindkey. So you will have traversed your two parent directories, but your shell prompt may still indicated that you are sitting in the directory from which you used the bindkey, even though you aren't.
Related
In Zsh, I have a key binding to go up by one directory (very useful):
# C-M-u: up-directory
up-directory() {
builtin cd .. && zle reset-prompt
}
zle -N up-directory
bindkey '\e\C-u' up-directory
It's very nice. So nice that I would like to get it as well in my Bash config.
How can we do that?
In case someone still need this:
This binds cd .. to F2. Keeps the currently typed command and throws an updated prompt.
bind '"\eOQ": "\C-a\C-kcd ..\C-m\C-y"'
How it works:
\eOQ is F2 on my terminal
C-a beginning-of-line
C-k kill-line
cd ..
C-m accept-line
C-y yank <- this restores the killed line
However the cd .. command appears in the screen. If it bothers you, use this instead:
bind -x '"\201":cd ..'
bind '"\eOQ": "\C-a\C-k\201\C-m\C-y"'
\201 is non existent key, an empty slot we can use.
Note1: It doesn't save the cursor position, after F2 the cursor lands on the end of the line, which is a little limitation.
Note2: The original was: bind '"\eOQ": " \C-a\C-k\201\C-m\C-y\C-b\C-d"' which adds an extra space, then removes it. I don't know why, maybe it was some workaround in the old ages when i wrote this, but it looks it does not needed now.
You can do that.
It's not as elegant or straight forward as with zsh but it's doable in bash using bind.
You can not only bind built in Readline functions (listed with bind -l) but other macros and shell functions too.
bind -m emacs -x '"\C-i":"cd .."' will bind a shell command (cd ..) to the keys (Ctrl+i) in emacs mode (the default mode). (Ctrl+i is unbound by default, u isn't)
Note that your prompt will probably not reflect the change.
If you leave out -x the string will instead be typed out for you so "cd ..\n" achieves the same result.
Edit: bind is how you bind keys and macros can accomplish what you want even though no built in thing exists.
If you end your PS1 prompt with \033[K (erase to eol) and can use bind -m emacs '"\C-i":" cd ..&&echo -e \"\\033[2A\"\n"' to do what you want.This will first print cd .. then control chars to move the cursor up and run it (with \n).
The end of your PS1 prevents it from showing. This is a hack but it shows that it's doable.
I want to be create an artisan command in Vim, so I can do something like:
:artisan make:migration create_blah_table --create=blah
And have it run the following:
ssh -t vagrant "cd /var/www && php artisan make:migration create_blah_table --create=blah"
Is this possible?
Update
The make:migration create_blah_table --create=blah bit could be anything.
See :help user-commands:
It is possible to define your own Ex commands. A user-defined command can act
just like a built-in command (it can have a range or arguments, arguments can
be completed as filenames or buffer names, etc), except that when the command
is executed, it is transformed into a normal Ex command and then executed.
For starters: See section |40.2| in the user manual.
*E183* *E841* *user-cmd-ambiguous*
All user defined commands must start with an uppercase letter, to avoid
confusion with builtin commands.
You want :command
:com[mand][!] [{attr}...] {cmd} {rep}
Define a user command. The name of the command is
{cmd} and its replacement text is {rep}. The command's
attributes (see below) are {attr}. If the command
already exists, an error is reported, unless a ! is
specified, in which case the command is redefined.
You can put this in your ~/.vimrc:
command -nargs=* Artisan !ssh -t vagrant "cd /var/www && php artisan <args>"
And then use the :Artisan make:migration create_blah_table --create=blah command in ex-mode.
I'm using GNU bash that is installed as git bash. On startup I need to change directory, so I'm doing it like this:
"C:\Program Files\Git\bin\sh.exe" --rcfile "./cd.sh"
Where cd.sh just contains cd /d/ command. Everything works fine here. Now I'm trying to get rid of cd.sh file and pass command to the shell as a parameter yet I want it to remain interactive, so I'm doing like this:
"C:\Program Files\Git\bin\sh.exe" -ic "cd /d"
It executes the command (tested with echo command) but then exits. Why doesn't it stay interactive?
From man bash:
An interactive shell is one started without non-option arguments and without the -c option ...
From man dash:
If no args are present and if the standard input of the shell is connected to a terminal (or if the -i flag is set), and the -c option is not present, the shell is considered an interactive shell.
Is there a way to have a shell script output text at the command prompt WITHOUT issuing the command?
CONTEXT: I SSH into a particular machine several times a day, and about 80% of the time, I type the same three commands as soon as I login. I would just put these commands in my .bashrc, but 20% of the time, I do NOT want to issue these commands. I'm wondering if there is some command I can put in .bashrc that will automatically put a string at my command line, so that when I login I see:
$ cd some/dir && ./some_script.sh
I could then just press enter 80% of the time or just clear the text the other 20% of the time.
(Inspired by Abdul Rehman's answer.)
Put this as the last line in your .bashrc file:
read -e -p "(Control-C to cancel) $ " -i "cd some/dir && ./some_script.sh" && eval "$REPLY"
read -e lets you enter a string using Readline for editing.
The -p provides a pseudo-prompt for this one-time command.
The -i provides a default string which you can edit or hit Enter to accept.
If you hit Enter, read sets the value of REPLY and exits with status 0, causing the following eval to execute. (Usually, eval is not a good command to use; however, here you would be presented with an interactive shell anyway, so there's not much risk here.) If you type Control-C instead, read exits with status 1 and the following eval is not executed, leaving you at your command prompt.
I know this is not what you asked but why don't use alias to shorten your command?
$ alias a='cd some/dir && ./some_script.sh'
Since you are going to use this often you could add this to you .bashrc file, so you don't have to set the alias every time.
After login you could just type a
$ a
I don't know of a way to do that but you could use history -s to push that command/those commands into the history when you log in which would then let you use !!<cr> or <up><cr> to execute them and just proceed normally if you don't.
history -s cd some/dir '&&' ./some_script.sh
You need to quote anything that the shell would normally evaluate/expand/remove. So the && in that example, any quotes, any semicolons, etc.
Put this script in .bashrc. It will ask you to run this command.
while true; do
read -p "Run this command?" yn
case $yn in
[Yy]* ) cd some/dir && ./some_script.sh; break;;
[Nn]* ) break;;
* ) echo "Enter Yes or No."
esac
done
You can run script on remote server instead loggin via ssh:
ssh <SERVER> some/dir/some_script.sh
For the remaining 20% you can connect ssh as usual.
If I open a shell into a machine with: putty -load session_name and then execute a command to add a job to a Grid queue on a linux system (qsub -cwd -b hostname), everything works fine.
But if I add the command to a text file, and then do putty -load session_name -m file.txt, I get qsub: command not found
If I back out and simplify the text file to be only the command hostname and use the -m option, it also works fine.
If I use the Connection->SSH->Remote command, and do something similar as the -m command, I get the same results as from the command line.
I'm very much a novice at linux systems, and this seems like it should be a simple fix to tell something that 'qsub' exists somewhere. Either that or there are some restrictions on these remote access things...
Edit:
Ok, so the initial question was how to run it--and I figured that out (add an absolute path), but there are other environment variable issues as well. It appears that qsub requires the SGE_ROOT variable to be set, but that isn't set for the remote commands window either.
So, a better question is, how do I get the putty remote commands shell (using -m) to open with the same properties and setup as a manual command line shell?
qsub is on your path when you log in interactively, but in the non-interactive shell it is not. Give the full path in the script, or set PATH in the script, and you ought to fix your problem.
It seems you need to run your command in the context of an interactive session, but the sshd protocol doesn't directly do that. So try invoking the command indirectly through /bin/sh.
/bin/sh -i -c "qsub -cwd -b hostname"
The -i makes the shell initialize itself like an interactive one, so it will load all the environment variables in your .profile or .bashrc that are loaded in a real interactive shell. The -c provides a command to run within that interactive shell.
You shouldn't have to explicitly set any paths this way since it works in an interactive session.