Hooking bash commands? - linux

I'm tired of doing long cd commands to other directories, so I want to make a little tool for jumping to the most recent folders.
I've searched and haven't found any sort of API that would let me trigger a process when a cd command is run. Can somebody point me in the right direction?
Working off the bash_history seems inefficient, and isn't always enabled.

There is a classic bash script that makes easier directory navigation: http://linuxgazette.net/109/marinov.html

Take a look at pushd and popd.

If you're using a fairly recent version of bash you can just Ctrl+R and type a few letters to get the history. So, if you press Ctrl+R and type cd you'll get your last cd command. Press Ctrl+R again and you're get second last cd command and so on.
And yes, cd - takes you to your last working directory.
You can also find your last working directory in shell variable $OLDPWD

Related

cd(Change Directory) command on linux

I am trying to code on Colab and if I take a look at the code its self similar with linux, therefore I am asking how the commands work on linux.
I am still confused the why cd on linux works. If I have code like this
cd A/B
it means to create new directory right?
after the first code then I write this
!wget https://abcd.com
does it mean I download file from https://abcd.com and store it at B path?
cd does not create anything, it just changes your shell's current working directory.
The ! in your next command is a bit weird, too. It indicates a history expansion of the most recent command line in your shell history starting with wget, adding https://abcd.com to that command line and then running it. That could be pretty much anything, depending on what your shell history contains.

A command to run the command that was executed right before the most recent one?

In bash, to run the most recent command you used, you can either press the up arrow key on your keyboard and press Enter or type !! and press Enter. But, is there a command that you can use to run the command that was executed right before the most recent one? For example:
$ pwd
/home/john
$ ls
bin Documents Music Pictures Templates
Desktop Downloads output Public Videos
Typing in !! and pressing Enter will run the ls command again. But, is there something similar to the !! command that will let you run the pwd command in the same manner? If there is one, give some more details as to how it works.
You can use !n, where n is line number in your history. To get the second to last command you can then use !-2.
You can use !-2 like is mentioned here. Along with the up arrow, you can cycle back through your history with ctrl-p as well, forward with ctrl-n. You can also use ctrl-r and do reverse search for a command you've already entered.
Did you remember the beginning characters of last executed commands,
you can execute it by specify the beginning characters of the command with !
from your question, to execute ls again, use the !l,
and !p or !pw to execute pwd command.but it only execute the last executed one.

"ls" command works sometimes and sometimes doesn't on Node.js

Please help me out, i am new. "ls" command for list doesn't work on my Node.js most times. It is not working now. However, it works sometimes though. How can i find list of current directory or file in Node.js?
As per to my tutorial for Node.js, i have to use command "ls" to see the list of my current directory or file.
When i press enter on ""ls" it replied "ls" is not found as internal or external command."
However, "ls" command shows the contents of file sometimes. I am using "ls" command for Desktop listing and another file in their. I do go to Desktop by cd Desktop. and then i only write "ls" then enter.
Please reply with simple explanation since i am new and learning Node.js.
i am taking Essential Node.js training from Lynda.com. "ls" did worked earlier though. "ls" does work on Window Shell and Bash all the time. Please reply. Thank You.
If not, what command i shall use for listing current directory or file contents?
Windows operational system provides the command dir instead of ls which should work similarly in your case:
Just use:
dir

Bash: call script with customized keyboard shortcuts?

Lets say I have a script, "myscript.sh", with contents being simply echo $PWD. I'd like to bind somehow this script to a key combo in bash (gnome-terminal) - so that when I press this key combination, the output of "myscript.sh" is inserted ("pasted") at the cursor position in the terminal.
Apparently, bash history and line manipulation is handled by readline - and the references I got for bash keyboard shortcuts, do reference readline:
bash keyboard shortcuts
Bash Reference Manual: Bindable Readline Commands
I've also seen in Bash Reference Manual: Readline Init File Syntax that the key bindings for bash can be listed by using bind -p (see help bind [not 'man bind'] for more). So maybe this question would better be titled as "_binding macros to custom keyboard shortcuts in readline" :) But in any case, is what I want possible to do?
I guess an alternative would be to have the script be something like "pwd | xsel -b", and then I call it on terminal - and I can paste afterwards; but I'd still like a single keyboard shortcut instead, say like Ctrl-Alt-H (which seems to be not used for anything), which will immediately insert/paste script output when pressed.
Thanks in advance,
Cheers!
EDIT: Just to clarify - here is my use case where I'd like this facility. I'm usually cd'd in a project folder, usually named something like myproject-folder-0012a, which is under revision control by svn. And there is a bunch of these folders. So quite often, I do commits where the first word of the message is the directory name, as in:
svn ci -m "myproject-folder-0012a: here a commit message"
But that is what I don't like - first I type 11 characters, which go rather fast:
svn ci -m "
And then, I cannot use autocompletion to get the name (i'm inside the folder) - which means I either have to fully type it (no way :)), or I copy paste it from the prompt (which requires selection - press mouse, drag, release mouse; then Ctrl+Shift+C, and then Ctrl+Shift+V, plus any left/right keys if I miss allignment - plus deletions and such if I make the copy wrong).
Meaning - so much work, just to get the bloody folder name for a bloody commit message :( I'd MUCH rather press something like (say) Ctrl-Alt-H, and have the folder name automatically inserted at cursor position, and be done with it :)
My suggestion for xsel is only because I could put it into a "global" script - say symlink it as /usr/bin/myscript (and obviously, the contents of the script are echo $(basename $PWD) rather than just pwd for my needs), and then I could do:
$ myscript # this puts directory name in clipboard
$ svn ci -m "[CTRL+SHIFT+V TO PASTE HERE]myproject-folder-0012a[NOW TYPE]: here a commit message"
... which sort of makes the workload less, but still - then I have to remember what the script name is, and call it, before I type the svn command (and I don't always remember that)... And still - I have to call a command, and then press a key combo; why shouldn't I just press a key combo once, and be done with it ??! :)
Well, hope this clarifies my problem a bit better ....
EDIT2: However, another reason why a bash keyboard shortcut would be useful, is that then I could also "paste/insert current directory name" not only in shell commands - but also in terminal programs, say like nano (where it would, arguably, be more difficult to use bash script or function expansion directly).
Simple version:
This command at a shell prompt:
bind '"\ee": "${PWD##*/}\e\C-e"'
or this line added to your ~/.inputrc:
"\ee": "${PWD##*/}\e\C-e"
will cause Alt-e to insert the basename of the current directory on the command line. It requires that the default binding of the readline function shell-expand-line which is \e\C-e be present (this could be adapted if it's different). I'm also making the assumption that you're using Bash's emacs mode.
Unfortunately, it causes things that have already been typed to be expanded as well. One of the affects of this is that after having typed:
svn ci -m "
and pressing Alt-e, the quotation mark will have disappeared. There are a couple of ways to deal with this.
One, assume that all you'll lose is the quote and either manually add it back or have the readline macro add it for you:
bind '"\ee": "${PWD##*/}\e\C-e\eb\"\C-e"'
which just isn't very satisfactory.
Advanced version:
Or, two, kill the line, do the insertion, then yank the line back:
bind '"\ee": " \C-u \C-a\C-k${PWD##*/}\e\C-e\C-y\C-a\C-y\ey\b"'
or
bind '"\ee": " \C-u \C-a\C-k${PWD##*/}\e\C-e\C-y\C-a\C-y\ey\b\ef\C-f"'
This leaves the rest of the line intact (nothing else is expanded or deleted), but it uses the kill ring, so it may leave it in a state that's different than you expect (if you're using it). It also inserts a space after the inserted directory name (the spaces in the macro are used to ensure that older kill-ring contents are not regurgitated if the macro is executed at the beginning or end of the line). The macro should work regardless of the position of the cursor in the line. The insertion will be made at the cursor's position, leaving the cursor in the same position [in the first version].
Edit: The second version leaves the cursor after the dirname and space that are inserted.
Edit 2:
The readline function shell-forward-word (unbound) does a better job than forward-word (\ef) for this. You can make use of that like this:
bind '"\ew":shell-forward-word'
bind '"\ee": " \C-u \C-a\C-k${PWD##*/}\e\C-e\C-y\C-a\C-y\ey\b\ew\C-f"'
By the way, you should know that Bash keyboard shortcuts are not active in other programs such as nano.
Ok, not really an answer, but I'd just like to summarize the comments I got so far, which are useful for my problem. However, the question as it stands - in respect to bash keyboard shortcuts running arbitrary scripts - is still not answered (I'd still prefer doing all this with a single key combo :))
First, I can use a 'global' script like:
$ sudo bash -c 'cat > /usr/bin/bpwd <<EOF
#!/bin/bash
basepwd=\$(basename \$(pwd))
echo -n \$basepwd # suppress line ending
# exec 1>/dev/null # debug: redir stdout to null
echo -n \$basepwd | xsel -i -b # suppress LF, and make xsel read from stdin
# exec 1>/dev/tty # debug: restore stdout
EOF
chmod +x /usr/bin/bpwd'
Or, I can add bash functions to my .bashrc (note: make sure you reload bash after you add these lines to .bashrc - for example, simply by typing bash in your current terminal):
$ echo '
bpwd2() { basepwd=${PWD##*/} ; echo -n $basepwd | xsel -i -b ; echo -n $basepwd ; }
svnci-test() { echo -n "$(bpwd2): $*" ; }
svnci-m() { svn ci -m "$(bpwd2): $*" ; }' >> ~/.bashrc
Basically, I misunderstood Reese Moore's suggestion originally - you can indeed use backticks - consider this command session (after the above commands have been ran):
$ bpwd
Desktop\
$ bpwd2
Desktop\
$ echo `bpwd`
Desktop
$ echo "`bpwd2` 2"
Desktop 2
This is what I needed to understand Moore's "the output from the backticked commands will be used as input on the executed command" (however, one also needs to take care to clean the line endings from the output); or, in my case, I can call
svn ci -m "`bpwd`: my message here"
# svn ci -m "${PWD##*/}: my message here" # alternatively
... or, I could follow camh's suggestion, and use svnci-m as a function (in my case, I almost never use additional arguments to svn ci, and so my version is slightly different). And to test whether arguments are passed correctly, I can use the svnci-test function:
$ svnci-test "my message"
Desktop: my message\
Thanks for the comments so far,
Cheers!
One way to do what you want with a single key press is to take advantage of programmable completion in bash. You possibly have some programmable completion set up with the bash_completion tool/package. If not, look into that to see the specifics of how it is done.
The idea is to have the programmable completion recognise when you have hit at the start of a svn commit message and then have it return a single completion which is the text you want to insert (the basename of the current directory).
I've only dabbled with programmable completion so I can't give you the details, but the above-mentioned bash_completion package or the subversion completion script may be a good start.

Run binary with ./ in Ubuntu

I decided to learn C++ (I program in C at work), and I have been reading some tutorials (and lots of posts here on Stack Overflow). OK, so I typed in the standard C++ "hello word", compiled with GCC on my Ubuntu machine as "test".
Then I tried to run it by typing "test" and hitting enter. Nothing. It turns out I must run it with "./test". OK, fine, I'll do that from now on. But why? The "./" just says that what I should run is in the current directory... Is the current directory not always part of the PATH when the OS is searching for something to run? Can I make it so?
Yes, the current directory is not part of your PATH. You don't want it to be, because then you could be in a directory that had a malicious program you didn't know about that you run.
What if you were used to running /usr/bin/grep, but you happened to be in a directory that a Bad Person put a malicious copy of grep in, and this time you run grep, and you're running grep out of the current directory, rather than /usr/bin/grep.
You certainly can add ./ to your PATH in your ~/.profile or ~/.bash_profile, but I don't recommend it.
And if it makes you feel any better, I had the same frustration 15 years ago when I started using Unix-like systems.
You can add "." to your PATH, but that won't help you in this case - "test" is a shell built in.
Unfortunately, there is a Unix command called "test"...
If there's a command line script you regularly run, you could set up a command line alias to rid yourself of the need to type ./ each time.
Even if the current directory is at the very beginning of the $PATH, 'test' still won't run it on (most?) shells, as 'test' is a shell built-in command.
Not having '.' (the current directory) in the PATH is a minor security measure. You could always add it in if you'd like, though it's not a best practice.
In case it's not clear, this is an aspect where Windows differs from Unix/Linux. On Windows, the current directory is implicitly in the path.

Resources