Insert current path in bash command line - bash

To run a program in bash, I normally use relative paths because it's faster to type; for example, something like
me#host:~/dir/appX$ ./manage.py runserver
The command will then be stored in the history. To recall the command from history (CTRL+R normally), I need to be on the same path as when I ran it, making the recall function less useful.
One solution is to insert the full path the first time, but it takes a lot of writing.
me#host:~/dir/appX$ /home/me/dir/appX/manage.py runserver
Is there a way (preferably built in) to insert the current path in the command line?
Or maybe a better solution (should work on bash)?

You can do this in bash using Tilde Expansion. You need two tilde expansion related features, just showing the relevant parts from man bash below:
Tilde Expansion
If the tilde-prefix is a `~+', the value of the shell variable PWD
replaces the tilde-prefix.
tilde-expand (M-&)
Perform tilde expansion on the current word.
As it says, you can type ~+ to get the current path. And then to expand it you need to type M-&. So the key sequence ~+M-& is all you need.
I found it a little difficult pressing all these keys, so I created a key binding for this. Add a line like below in your ~/.inputrc file:
"\C-a":"~+\e&"
With this I can now type ctrl+a on my keyboard to get the current path on the command line.
PS: It's possible that ctrl+a is already bound to something else (perhaps beginning of line) in which case it might be better to use another key combination. Use bind -p to check current bindings.

Related

macos: Bash shows commands instead files

Bash on my macOS shows all (probably) commands from $PATH when I double-TAB instead of files and folders. Same when I can use TAB once - it does not work at all. Commands like CD works fine.
I have no idea where the problem is - $PATH seems normal to me:
/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
~/.profile is this:
export PATH=/usr/local/php5/bin:$PATH
export PATH="$HOME/.yarn/bin:$PATH"
~/.bash_profile has only this:
export PATH="/usr/local/sbin:$PATH"
Same behavior under PhpStorm's terminal. So I believe, the problem is somewhere deeper.
Can you help, please?
Command-line completion in Bash is achieved through readline, a well-known utility library used by many GNU and other Open Source products.
Basic completion is using the {TAB} key, and the actual completion depends on context. If the text does not start with a special character then commands are listed if they match, only if commands don't match are filenames listed.
If completion can be achieved, enough characters are supplied to make the completion unique, then it will be done, otherwise a second {TAB} will give a list of possibilities.
From man bash (Completing):
Bash attempts completion treating the text as a variable (if the text
begins with $), username (if the text begins with ~), hostname
(if the text begins with #), or command (including aliases and
functions) in turn. If none of these produces a match, filename
completion is attempted.

How to make fish shell delete words like bash does

I'm giving a second try to the fish shell. One thing that really annoys me is the "new" behaviour of Ctrl+w shortcut.
Consider following situation:
$ vim ~/.config/fish/config.fish
...having the cursor at the end of the line.
When you press Ctrl+w, following happens:
in bash: ~/.config/fish/config.fish is deleted
in fish: only config.fish is deleted
How can I make fish delete words that are separated by spaces only?
"\cw" (in fish's notation) is bound to "backward-kill-path-component" (which bind \cw will tell you).
If you wish, you can bind it to something else, including input functions like "backward-kill-word" or any fish script - bind \cw backward-kill-word or bind \cw "commandline -rt ''" (which will remove the entire current token) or bind \cw backward-kill-bigword. See the bind documentation or bind --help for more information.
The difference between "word" and "bigword" here is that "word" will only go to the next non-word-character, which can be a "." or "/" or "-", among others, while "bigword" will truly go to the next whitespace character.
Note that the "bigword" functions have only been introduced in fish 2.3.0.
You can try these incantations in an interactive shell. If you decide to make it permanent, you'll need to add them to a function called fish_user_key_bindings.

Bash:script cannot be called after adding the path

I am writing my own unix scripts so I want to add a new directory for Bash. I add sth in .bash_profile like this.
PATH="~/Documents:${PATH}"
export PATH
and in my ~/Documents, there is a file named test of which the content is
#!/usr/bin/env python3.5
print("hahahhah")
I also used
chmod 755 test
to make it executable.
But I cannot call it in terminal directly. ./test works as usual.
What went wrong?
After I change to
PATH="$HOME/Documents:${PATH}"
export PATH
nothing happens.
FDSM_lhn#9-53:~/Documents$ test
FDSM_lhn#9-53:~/Documents$ ./test
hahahhah
Solution:
The fundamental reason is that I have a command of the same name as default one, So it won't work any way! Changing name will be sufficient!
Tilde doesn't get expanded inside strings. So by quoting the right-hand side of the assignment you prevent it from being expanded and get a literal ~ in your PATH variable which doesn't help you any.
You have two ways to fix this:
Drop the quotes on the assignment (yes this is safe, even for $PATH values with spaces, etc.).
Use $HOME instead of ~.
I prefer the second solution but the first is entirely valid for this case.
Beware though that in places where you aren't doing a straight assignment you often cannot just drop the quotes and trying to use ~ will cause problems.
In which case you will end up finding a question like this with an answer like this and something ugly like this.

Blacklist program from bash completion

Fedora comes with "gstack" and a bunch of "gst-" programs which keep appearing in my bash completions when I'm trying to quickly type my git aliases. They're of course installed under /usr/bin along with a thousand other programs, so I can't just remove their directory from my PATH. Is there any way in Linux to blacklist these specific programs from appearing for completion?
I've tried the FIGNORE and GLOBIGNORE environment variables but they don't work, it looks like they're only for file completion after you've entered a command.
In 2016 Bash introduced an option for that. I'm reproducing the text from this newer answer by zuazo:
This is rather new, but in Bash 4.4 you can set the EXECIGNORE variable:
aa. New variable: EXECIGNORE; a colon-separate list of patterns that
will cause matching filenames to be ignored when searching for commands.
From the official documentation:
EXECIGNORE
A colon-separated list of shell patterns (see Pattern Matching) defining the list of filenames to be ignored by command search using
PATH. Files whose full pathnames match one of these patterns are not
considered executable files for the purposes of completion and command
execution via PATH lookup. This does not affect the behavior of the [,
test, and [[ commands. Full pathnames in the command hash table are
not subject to EXECIGNORE. Use this variable to ignore shared library
files that have the executable bit set, but are not executable files.
The pattern matching honors the setting of the extglob shell option.
For Example:
$ EXECIGNORE=$(which pytest)
Or using Pattern Matching:
$ EXECIGNORE=*/pytest
I don't know if you can blacklist specific files, but it is possible to complete from your command history instead of the path. To do that add the following line to ~/.inputrc:
TAB dynamic-complete-history
FIGNORE is for SUFFIXES only. It presumes for whatever reason that you want to blacklist an entire class of files. So you need to knock off the first letter.
E.g. To eliminate gstack from autocompletion:
FIGNORE=stack
Will rid gstack but also rid anything else ending in stack.

ZSH script and prompt profiling?

This answer, "How to profile a bash shell script?", seems to nearly perfectly cover what I'm trying to accomplish here. I currently have some zsh scripts that modify the prompt, however I think some updates to oh-my-zsh have evoked some issues that I need to hunt down. The sluggishness from time to time is unbearable.
To this end, how would you adapt the prompt sections in this example answer to work with zsh vs bash?
Presently I have modified /etc/zshenv such that it has the initial suggested code from the example:
PS4='+ $(date "+%s.%N")\011 '
exec 3>&2 2>/tmp/bashstart.$$.log
set -x
And my ~/.zshrc has the following appended to it's tail:
set +x
exec 2>&3 3>&-
Of course these are not valid for ZSH shell customization. My prompt rendering code utilizes oh-my-zsh customizations. I could prepend the appropriate code to the prompt I suppose or I'm open to other suggestions.
Calling date for each command will fork and exec, which adds overhead which may interfere with your measurements.
Instead, you could use
PS4=$'+ %D{%s.%6.}\011 '
to log timestamps with lower overhead (up to millisecond precision).
For some notes on processing the resulting logs, see http://blog.xebia.com/profiling-zsh-shell-scripts/
You may need to do
setopt prompt_subst
if it's not already.
Also, in order to interpret the octal escape for tab, use $'':
PS4=$'+ $(date "+%s.%N")\011 '
You may also find some of these escapes to be useful:
%? The return status of the last command executed just before the prompt.
%_ The status of the parser, i.e. the shell constructs (like `if' and `for') that have been started on the command
line. If given an integer number that many strings will be printed; zero or negative or no integer means print as
many as there are. This is most useful in prompts PS2 for continuation lines and PS4 for debugging with the
XTRACE option; in the latter case it will also work non-interactively.
%i The line number currently being executed in the script, sourced file, or shell function given by %N. This is most
useful for debugging as part of $PS4.
%I The line number currently being executed in the file %x. This is similar to %i, but the line number is always a
line number in the file where the code was defined, even if the code is a shell function.
%L The current value of $SHLVL.
%N The name of the script, sourced file, or shell function that zsh is currently executing, whichever was started
most recently. If there is none, this is equivalent to the parameter $0. An integer may follow the `%' to spec‐
ify a number of trailing path components to show; zero means the full path. A negative integer specifies leading
components.
%x The name of the file containing the source code currently being executed. This behaves as %N except that function
and eval command names are not shown, instead the file where they were defined.

Resources