Does linux have commands allow me to push my regularly used commands into a stack or something so that I can easily fetch them from it and jump among the most frequently used commands as much as I want.
I know we can create alias for commands, but that's not what I am looking for here. My case is more like I have a few horrible long directories, I need to be able to switch between them quickly and frequently. eg.
cd /pathA/pathB/pathC/pathD/
cd /pathE/pathF/pathG/pathH/
vim /pathA/pathB/pathC/pathD/test.txt
.......
I don't really want to create alias for each command here because the paths vary quite often as well, I don't want to constantly update my alias.
Regarding directories, you can push the paths on stack
pushd path_you_want_to_store
popd
Well, there's the history feature of your shell that would allow you to recall previous commands.
A quick command for going back and forth between the last 2 directories is
cd -
As far as more directories are concerned, I use this set of aliases in my .tcshrc to keep track of them. If I am in a directory I want to remember I just say
keep
or
keep2
and then later I can get back there by simply typing
cd $k
or
cd $k2
If I want to see the directories I have "saved" I type
ks
I can also use these variable for other operations such as cp/mv (and quite frequently this is what I do to save on typing long path names).
You didn't specify your shell, so this is using the tcsh but could be easily adapted to any other shell as long as you know how to set up equivalent aliases. This allows me to save up to 6 different directories, you can decide how many you set up.
This is my own "homegrown" solution that has served me well for the last 10+ years, there might be others, perhaps "built-in". At this point I use these automatically and so regularly that I don't even think of them as aliases.
alias keep 'set k=`pwd`'
alias keep2 'set k2=`pwd`'
alias keep3 'set k3=`pwd`'
alias keep4 'set k4=`pwd`'
alias keep5 'set k5=`pwd`'
alias keep6 'set k6=`pwd`'
alias ks 'echo $k; echo $k2; echo $k3; echo $k4; echo $k5; echo $k6'
Write your 'long path' once and fetch it next time by pressing "Ctrl + r".
You need to press "Ctrl + r" first. Then start typing your 'long path' it will start showing you the path you have already typed.
To find existence of more old records (of the same text you have typed) keep pressing "Ctrl + r" and it will show you the old records.
Also check out the CDPATH variable, that can hold a list of common directories that you want to jump into - eg :
export CDPATH=/pathA/pathB/pathC
cd pathD
# now you're at /pathA/pathB/pathC/pathD
If you feel the command will be used frequently you could add a tag
command #useful
Then
[ctrl+r] #useful
Related
hi i'd like to get some help with my linux bash homeworks.
i have to make a script that gets a directory and returns the depth of the deepest subdirectory (+1 for each directory).
I must do it recursively.
I must use 'list_dirs.sh' that takes the virable dir and echo its subdirs.
thats what i got so far:
dir=$1
sub=`source list_dirs.sh`
((depth++))
for i in $sub
do
if [ -n "$sub" ] ; then
./depthScript $dir/$i
fi
done
if ((depth > max)) ; then
max=$depth
echo $max
fi
after testing with a dir that supose to return 3 I got insted:
1
1
1
1
it seems like my depth counter forget previous values and I get output for
each directory.. need some help!
You can use bash functions to create recursive function calls.
Your function would ideally echo 0 in the base case where it is called on a directory with no subdirectories, and echo 1+$(getDepth $subdir) in the case where some subdirectory $subdir exists. See this question on recursive functions in bash for a framework.
When you run a script normally (i.e. it's in your PATH and you just enter its name, or you enter an explicit path to it like ./depthScript), it runs as a subprocess of the current shell. This is important because each process has its own variables. Variables also come in two kinds: shell variables (which are only available in that one process) and environment variables (the values of which get exported to subprocesses but not back up from them). And depending on where you want a variable's value to be available, there are three different ways to define them:
# By default, variables are shell variable that's only defined in this process:
shellvar=something
# `export` puts a variable into the environment, so it'll be be exported to subprocesses.
# You can export a variable either while setting it, or as a separate operation:
export envvar=something
export anotherenvvar
anotherenvvar=something
# You can also prefix a command with a variable assignment. This makes an
# environment variable in the command process's environment, but not the current
# shell process's environment:
prefixvar=something ./depthScript $dir/$i
Given the above assignments:
shellvar is defined in the current shell process, but not in any other process (including the subprocess created to run depthScript).
envvar and anotherenvvar will be inherited by the subprocess (and its subprocesses, and all subprocesses for later commands), but any changes made to it in those subprocesses have no effect at all in the current process.
prefixvar is available only in the subprocess created to run depthScript (and its subprocesses), but not in the current shell process or any other of its subprocesses.
Short summary: it's a mess because of the process structure, and as a result it's best to just avoid even trying to pass values around between scripts (or different invocations of the same script) in variables. Use environment variables for settings and such that you want to be generally available (but don't need to be changed much). Use shell variables for things local to a particular invocation of a script.
So, how should you pass the depth values around? Well, the standardish way is for each script (or command) to print its output to "standard output", and then whatever's using the script can capture its output to either a file (command >outfile) or a variable (var=$(command)). I'd recommend the latter in this case:
depth=$(./depthScript "$dir/$i")
if ((depth > max)) ; then
max=$depth
fi
Some other recommendations:
Think your control and data flow through. The current script loops through all subdirectories, then at the end runs a single check for the deepest subdir. But you need to check each subdirectory individually to see if it's deeper than the current max, and at the end report the deepest of them.
Double-quote your variable references (as I did with "$dir/$i" above). Unquoted variable references are subject to word splitting and wildcard expansion, which is the source of much grief. It looks like you'll need to leave $sub unquoted because you need it to be split into words, but this will make the script unable to cope with directory names with spaces. See BashFAQ #20: "How can I find and safely handle file names containing newlines, spaces or both?"
The if [ -n "$sub" ] ; then test is irrelevant. If $sub is empty, the loop will never run.
In a shell script, relative paths (like ./depthScript) are relative to whatever the working directory of the parent process, not to the location of the script. If someone runs your script from another directory, ./depthScript will not work. Use "$BASH_SOURCE" instead. See BashFAQ #28: "How do I determine the location of my script? I want to read some config files from the same place."
When trying to troubleshoot a script, it can help to put set -x before the troublesome section. This makes the shell print each command as it runs, so you can see what's going on.
Run your scripts through shellcheck.net -- it'll point out a lot of common mistakes.
I would like to define some aliases in fish. Apparently it should be possible to define them in
~/.config/fish/functions
but they don't get auto loaded when I restart the shell. Any ideas?
Just use alias. Here's a basic example:
# Define alias in shell
alias rmi "rm -i"
# Define alias in config file ( `~/.config/fish/config.fish` )
alias rmi="rm -i"
# This is equivalent to entering the following function:
function rmi
rm -i $argv
end
# Then, to save it across terminal sessions:
funcsave rmi
This last command creates the file ~/.config/fish/functions/rmi.fish.
Interested people might like to find out more about fish aliases in the official manual.
This is how I define a new function foo, run it, and save it persistently.
sthorne#pearl~> function foo
echo 'foo was here'
end
sthorne#pearl~> foo
foo was here
sthorne#pearl~> funcsave foo
For posterity, fish aliases are just functions:
$ alias foo="echo bar"
$ type foo
foo is a function with definition
function foo
echo bar $argv;
end
To remove it
$ unalias foo
/usr/bin/unalias: line 2: unalias: foo: not found
$ functions -e foo
$ type foo
type: Could not find “foo”
If you add an abbr instead of an alias you'll get better auto-complete. In fish abbr more closely matches the behavior of a bash alias.
abbr -a gco "git checkout"
Will -add a new abbreviation gco that expands to git checkout.
Here's a video demo of the resulting auto-complete features
fish starts by executing commands in ~/.config/fish/config.fish.
You can create it if it does not exist:
vim ~/.config/fish/config.fish
and save it with :wq
step1. make configuration file (like .bashrc)
config.fish
step2. just write your alias like this;
alias rm="rm -i"
Save your files as ~/.config/fish/functions/{some_function_name}.fish and they should get autoloaded when you start fish.
if there is not config.fish in ~/.config/fish/, make it.
there you can write your function .function name; command; end
I know there are 11 answers already at this point, and they all work, but most are also suboptimal in 2022 (and for the past few years).
Short, updated, current answer for all releases since 3.0b1:
The quickest and best way to do what is requested in this question is:
alias -s <aliasname> "command(s)" # Or --save
Important: Simply do this one time per alias at the command-line. Do not add it to your startup config.
To list existing aliases which have been defined this way (since fish 2.5b1):
alias
To edit an alias created this way:
funced -s <aliasname> # or --save
To remove an alias defined this way (since fish 3.4.0):
functions -e <aliasname> # or --erase
funcsave <aliasname>
Note that since 3.4.0 was only released a few weeks ago, I'll include the commands that work in previous versions as well:
functions -e <aliasname> # or --erase
rm ~/.config/fish/functions/<aliasname>.fish
Ironically, you may even want to alias this into unalias. You'll need to first alias -s unalias the functions -e ... part, then funced -s unalias again to add the rm ....
Note that #nemanja's answer does include the alias -s command, but doesn't go into much detail. Regardless, since it predates mine, I wouldn't mind at all if it was the accepted answer. However, the currently accepted answer is a bit outdated. While it could, in theory, be edited, the necessary changes, IMHO, would create a different answer, which we aren't supposed to do.
While #nemanja's answer is the best solution for current fish releases, I'm writing this as a separate answer to:
Go into more detail on why ('alias -s`) is the best solution.
Go into more detail on why the other answers are suboptimal with current fish releases.
Provide the additional information on editing and removing aliases which are defined this way.
Much more detail on why the above is preferred over the other answers
First, it is important to understand that, as Glenn Jackman (a former fish shell contributor) mentioned in this answer, the alias command in fish is just syntactic sugar for creating a function.
However, when you define an alias this way, it is defined only in memory. It is not persisted. That ability was added shortly after that answer was written.
Outdated method #1
With that in mind, the currently accepted answer from 2010 has a few issues nowadays.
First, you really shouldn't define your aliases in your config. That may have been correct in 2010, but even then I think fish supported lazy-loading of functions/aliases, which is a better option. Defining functions/aliases in your startup config is the "bash/zsh way". Fish is better than that ...
One of the (many) features that sets fish apart from bash and zsh is lazy-loading. Lazy is good in this case. You want lazy-loading. You need lazy-loading (ok, well maybe not need), but anyway ...
As the original question mentioned, it is possible to define your functions in ~/.config/fish/functions/, although it is a directory rather than a file. Note that this will be $XDG_CONFIG_HOME/fish/functions if that variable is defined.
Functions in this directory are lazy-loaded.
Lazy loading means:
Fish does not load any part of your alias/function when it starts. This can speed up launch times significantly, especially if you have many aliases and/or complex functions, or perhaps are running on a slower system/VM/shared CPU host.
No part of the function other than the name (for lookup purposes) is loaded into memory until it is used.
The first time you call a function with functionname, then and only then will fish lazy-load the function from ~/.config/fish/functions/<functionname.fish>.
How much of a difference this will make will depend on a lot of factors, but personally, I keep a lookout for simple ways to optimize my configuration. One of the main factors that drove me from Zsh to fish was the increasingly slow startup of my Zsh config as I added features, functions, etc. We've made the switch to a better shell (in our opinion, I assume) -- Why not take advantage of its improved features?
This lazy-loading might sound complicated, but it's almost exactly what the alias -s command does for us without any additional effort.
In addition, the alias command, goes several steps further and automatically adds a --wraps <original_command> argument to your function so that you get the added benefit of completions. It also adds a --description, which is used to describe the function as an "alias". As a result, running just:
alias
... by itself will give you a list of all functions/aliases defined this way.
Other answers
Three separate answers also all mention using ~/.config.fish/config.fish, either with function declarations or alias commands.
As with the original answer, this is the suboptimal, bash/zsh way of doing things. This means that your aliases/functions will be processed and loaded every time you start a new shell.
I recommend that you take advantage of lazy-loading instead.
mkalias function
This answer by #Mike defines a mkalias function that creates and saves the alias. A very good solution at the time (and IMHO should have had more upvotes), but it predated fish release 3.0 which added alias --save/-s, which now does the same thing.
abbr command
#TobiasMühl's answer recommends using the abbr command, which is a reasonable alternative. However, note that alias does handle completions, and in pretty much the same manner as the abbr example given in that answer.
alias -s gco "git checkout"
And completions will be based on git checkout, just as if it were an expanded abbreviation.
There may be some cases where the completions will be more accurate because abbreviations are expanded as soon as the Space is pressed after typing the abbreviation name.
That's one of the fundamental differences between abbreviations and aliases in fish. Abbreviations are expanded at the prompt; aliases are not.
Another difference is that abbreviations are stored in variables, which are processed/loaded at shell startup (whether universal or global/config). As mentioned above, aliases are lazy-loaded.
And yet another difference is that aliases, since they are functions, can be much more complex. For instance, I have my ls set to be exa with the output piped to bat. It's just not possible define that in an abbreviation.
That said, again, abbreviations are a feature to consider using in fish. I do plan to shift a few of my aliases to abbreviations, since I have some where I want to change the arguments after expansion; something that's not possible with the unexpanded aliases.
To properly load functions from ~/.config/fish/functions
You may set only ONE function inside file and name file the same as function name + add .fish extension.
This way changing file contents reload functions in opened terminals (note some delay may occur ~1-5s)
That way if you edit either by commandline
function name; function_content; end
then
funcsave name
you have user defined functions in console and custom made in the same order.
#bozhidar-batsov gave an absolutely complete answer that helps one understand the inner workings of the alias/function in fish. Reading fish documentation for an alias, there is also a -s flag that is really convenient to use, but I didn't see anyone mention it.
-s or --save Automatically save the function created by the alias into your fish configuration directory using funcsave.
One-line solution for defining and saving an alias (for example):
alias cl 'clear' -s. Instantly works across all sessions and is persisted.
Navigate to the ~/.config/fish/functions/ and you'll see cl.fish file.
# Defined via `source`
function cl --wraps=clear --description 'alias cl clear'
clear $argv;
end
make a function in ~/.config/fish/functions called mkalias.fish and put this in
function mkalias --argument key value
echo alias $key=$value
alias $key=$value
funcsave $key
end
and this will create aliases automatically.
I found the prior answers and comments to be needlessly incomplete and/or confusing. The minimum that I needed to do was:
Create ~/.config/fish/config.fish. This file can optionally be a softlink.
Add to it the line alias myalias echo foo bar.
Restart fish. To confirm the definition, try type myalias. Try the alias.
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 11 years ago.
Improve this question
Command completion in bash(1) is quite handy; I like this feature very much. But I have a question.
For example, we all have Documents and Downloads in $HOME directory.
So if I input cd ~ and then press TAB, then it will traverse all the directory under $HOME. When Documents come up and the shell now displays cd ~/Documents, I want to go deeper into this directory. For example, there is a work directory in Documents. My intention is to cd to the work directory.
So what should I do?
I usually input a w then press TAB, but when this action repeats too much I found it quite annoying. And sometimes I don't know exactly what files are under this directory.
Do you have any good ideas?
ps: In fact, i met this problem when i was using vim. I input :e then TAB, it will cycle the subfolders, the only way i found to stop the cycling and enter the next level is input a /. So the path has double '/' in the end.
You could switch your shell to ZShell, which allows you to tab through directories without typing the first letter.
For example, you can type
cd ~/
Pressing TAB will bring up a list of all subfolders (like in bash), but pressing TAB multiple times will allow you to cycle through the subfolders. Pressing the -> or / key will allow you to start tab-completing inside that directory, and so on.
You can sometimes use chsh (man chsh for more info) to change your shell, if it's your own personal machine, or your network might have a special way to change your shell. You might also want to Google for some common .zshrc / .zshenv settings or migrate your old .bashrc / .cshrc / .profile settings.
Zsh also has ways to set up TAB completion for other tasks, for example, it can TAB complete svn files based on those that aren't already in SVN (for svn add). To get these features, add
autoload -U compinit
compinit
to your .zshrc file. There are plenty more ways to customize your TAB completion in zsh (such as with case-insensitivity, or for arguments to different programs), but if you're interested in those, you can probably find more information than I know by searching.
Like the Jack Toole's zsh suggestion (which is a perfectly fine shell), if you have to use bash, you can stick this in your .bashrc for the same "continue to hit tab cycle through possibilities" feature:
test -n "$PS1" && bind TAB:menu-complete
There's also a project called bash-completion that provides a lot of other kinds of completion other than pathname completion.
If you don't know what is in the directory, just press TAB one more time.
Is is possible to have the history of a specific user in one more file other than the default file mentioned as HISTFILE?
I would like to have as backup file if main file was removed and let it be like a backup for that one.
Regards,
Sriharsha Kalluru.
You can create a hardlink to the file
cp --link --verbose /home/$USER/.bash_history /somewhere/else/users_history
When the original file in his home is removed the file is still there and preserves the content from being lost.
Many times I've found myself using Ctrl-R in Bash to get a old command four times the terminal width, just to find out that too many days have passed and it's no longer in the .bash_history file. Here are two lines that will keep track of every command line you type at the bash prompt and use no external processes at all, just plain bash.
My first approach to this problem was increasing the maximum number of lines in the history to a very large quantity. But no matter how large it was, there was always a moment when I needed a long command I typed many months ago and it had already left the history. The current solution came to my mind when I learned about the PROMPT_COMMAND variable, a command that bash executes before showing each prompt. Here are the two lines:
export HISTTIMEFORMAT="%s "
PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND ; }"'echo $$ $USER \
"$(history 1)" >> ~/.bash_eternal_history'
One goal I set to myself was to achieve it without using any external process, so bash wouldn't have to fork a new process after every ENTER pressed at its prompt. The first line sets the format of history lines to include the date as a Unix timestamp, so you can now when you typed every command. The second line, which is the core of the solution, first ensures that, if a previous PROMPT_COMMAND was set, it gets executed before our stuff and then appends a line of the format:
PID USER INDEX TIMESTAMP COMMAND
to a file called .bash_eternal_history in the current user home.
Adding the username, which at first seemed unnecesary, became useful later to distiguish between "sudo -s" sessions and normal sessions which retain the same value for "~/", and so append lines to the same .bash_eternal_history file.
I hope some of you find these two lines as useful as I do. :-)
Would hard links solve your problem?
Also you can read the man page here.
i would write a cronjob that copies the original histfiel to a backuplocation every minute or so. the you don't have to worry about defining a second histfile.
otherwise you could write every command the user enters to a alternate file
for this approach take a look here:
bash, run some command before or after every command entered from console
I would like to define some aliases in fish. Apparently it should be possible to define them in
~/.config/fish/functions
but they don't get auto loaded when I restart the shell. Any ideas?
Just use alias. Here's a basic example:
# Define alias in shell
alias rmi "rm -i"
# Define alias in config file ( `~/.config/fish/config.fish` )
alias rmi="rm -i"
# This is equivalent to entering the following function:
function rmi
rm -i $argv
end
# Then, to save it across terminal sessions:
funcsave rmi
This last command creates the file ~/.config/fish/functions/rmi.fish.
Interested people might like to find out more about fish aliases in the official manual.
This is how I define a new function foo, run it, and save it persistently.
sthorne#pearl~> function foo
echo 'foo was here'
end
sthorne#pearl~> foo
foo was here
sthorne#pearl~> funcsave foo
For posterity, fish aliases are just functions:
$ alias foo="echo bar"
$ type foo
foo is a function with definition
function foo
echo bar $argv;
end
To remove it
$ unalias foo
/usr/bin/unalias: line 2: unalias: foo: not found
$ functions -e foo
$ type foo
type: Could not find “foo”
If you add an abbr instead of an alias you'll get better auto-complete. In fish abbr more closely matches the behavior of a bash alias.
abbr -a gco "git checkout"
Will -add a new abbreviation gco that expands to git checkout.
Here's a video demo of the resulting auto-complete features
fish starts by executing commands in ~/.config/fish/config.fish.
You can create it if it does not exist:
vim ~/.config/fish/config.fish
and save it with :wq
step1. make configuration file (like .bashrc)
config.fish
step2. just write your alias like this;
alias rm="rm -i"
Save your files as ~/.config/fish/functions/{some_function_name}.fish and they should get autoloaded when you start fish.
if there is not config.fish in ~/.config/fish/, make it.
there you can write your function .function name; command; end
I know there are 11 answers already at this point, and they all work, but most are also suboptimal in 2022 (and for the past few years).
Short, updated, current answer for all releases since 3.0b1:
The quickest and best way to do what is requested in this question is:
alias -s <aliasname> "command(s)" # Or --save
Important: Simply do this one time per alias at the command-line. Do not add it to your startup config.
To list existing aliases which have been defined this way (since fish 2.5b1):
alias
To edit an alias created this way:
funced -s <aliasname> # or --save
To remove an alias defined this way (since fish 3.4.0):
functions -e <aliasname> # or --erase
funcsave <aliasname>
Note that since 3.4.0 was only released a few weeks ago, I'll include the commands that work in previous versions as well:
functions -e <aliasname> # or --erase
rm ~/.config/fish/functions/<aliasname>.fish
Ironically, you may even want to alias this into unalias. You'll need to first alias -s unalias the functions -e ... part, then funced -s unalias again to add the rm ....
Note that #nemanja's answer does include the alias -s command, but doesn't go into much detail. Regardless, since it predates mine, I wouldn't mind at all if it was the accepted answer. However, the currently accepted answer is a bit outdated. While it could, in theory, be edited, the necessary changes, IMHO, would create a different answer, which we aren't supposed to do.
While #nemanja's answer is the best solution for current fish releases, I'm writing this as a separate answer to:
Go into more detail on why ('alias -s`) is the best solution.
Go into more detail on why the other answers are suboptimal with current fish releases.
Provide the additional information on editing and removing aliases which are defined this way.
Much more detail on why the above is preferred over the other answers
First, it is important to understand that, as Glenn Jackman (a former fish shell contributor) mentioned in this answer, the alias command in fish is just syntactic sugar for creating a function.
However, when you define an alias this way, it is defined only in memory. It is not persisted. That ability was added shortly after that answer was written.
Outdated method #1
With that in mind, the currently accepted answer from 2010 has a few issues nowadays.
First, you really shouldn't define your aliases in your config. That may have been correct in 2010, but even then I think fish supported lazy-loading of functions/aliases, which is a better option. Defining functions/aliases in your startup config is the "bash/zsh way". Fish is better than that ...
One of the (many) features that sets fish apart from bash and zsh is lazy-loading. Lazy is good in this case. You want lazy-loading. You need lazy-loading (ok, well maybe not need), but anyway ...
As the original question mentioned, it is possible to define your functions in ~/.config/fish/functions/, although it is a directory rather than a file. Note that this will be $XDG_CONFIG_HOME/fish/functions if that variable is defined.
Functions in this directory are lazy-loaded.
Lazy loading means:
Fish does not load any part of your alias/function when it starts. This can speed up launch times significantly, especially if you have many aliases and/or complex functions, or perhaps are running on a slower system/VM/shared CPU host.
No part of the function other than the name (for lookup purposes) is loaded into memory until it is used.
The first time you call a function with functionname, then and only then will fish lazy-load the function from ~/.config/fish/functions/<functionname.fish>.
How much of a difference this will make will depend on a lot of factors, but personally, I keep a lookout for simple ways to optimize my configuration. One of the main factors that drove me from Zsh to fish was the increasingly slow startup of my Zsh config as I added features, functions, etc. We've made the switch to a better shell (in our opinion, I assume) -- Why not take advantage of its improved features?
This lazy-loading might sound complicated, but it's almost exactly what the alias -s command does for us without any additional effort.
In addition, the alias command, goes several steps further and automatically adds a --wraps <original_command> argument to your function so that you get the added benefit of completions. It also adds a --description, which is used to describe the function as an "alias". As a result, running just:
alias
... by itself will give you a list of all functions/aliases defined this way.
Other answers
Three separate answers also all mention using ~/.config.fish/config.fish, either with function declarations or alias commands.
As with the original answer, this is the suboptimal, bash/zsh way of doing things. This means that your aliases/functions will be processed and loaded every time you start a new shell.
I recommend that you take advantage of lazy-loading instead.
mkalias function
This answer by #Mike defines a mkalias function that creates and saves the alias. A very good solution at the time (and IMHO should have had more upvotes), but it predated fish release 3.0 which added alias --save/-s, which now does the same thing.
abbr command
#TobiasMühl's answer recommends using the abbr command, which is a reasonable alternative. However, note that alias does handle completions, and in pretty much the same manner as the abbr example given in that answer.
alias -s gco "git checkout"
And completions will be based on git checkout, just as if it were an expanded abbreviation.
There may be some cases where the completions will be more accurate because abbreviations are expanded as soon as the Space is pressed after typing the abbreviation name.
That's one of the fundamental differences between abbreviations and aliases in fish. Abbreviations are expanded at the prompt; aliases are not.
Another difference is that abbreviations are stored in variables, which are processed/loaded at shell startup (whether universal or global/config). As mentioned above, aliases are lazy-loaded.
And yet another difference is that aliases, since they are functions, can be much more complex. For instance, I have my ls set to be exa with the output piped to bat. It's just not possible define that in an abbreviation.
That said, again, abbreviations are a feature to consider using in fish. I do plan to shift a few of my aliases to abbreviations, since I have some where I want to change the arguments after expansion; something that's not possible with the unexpanded aliases.
To properly load functions from ~/.config/fish/functions
You may set only ONE function inside file and name file the same as function name + add .fish extension.
This way changing file contents reload functions in opened terminals (note some delay may occur ~1-5s)
That way if you edit either by commandline
function name; function_content; end
then
funcsave name
you have user defined functions in console and custom made in the same order.
#bozhidar-batsov gave an absolutely complete answer that helps one understand the inner workings of the alias/function in fish. Reading fish documentation for an alias, there is also a -s flag that is really convenient to use, but I didn't see anyone mention it.
-s or --save Automatically save the function created by the alias into your fish configuration directory using funcsave.
One-line solution for defining and saving an alias (for example):
alias cl 'clear' -s. Instantly works across all sessions and is persisted.
Navigate to the ~/.config/fish/functions/ and you'll see cl.fish file.
# Defined via `source`
function cl --wraps=clear --description 'alias cl clear'
clear $argv;
end
make a function in ~/.config/fish/functions called mkalias.fish and put this in
function mkalias --argument key value
echo alias $key=$value
alias $key=$value
funcsave $key
end
and this will create aliases automatically.
I found the prior answers and comments to be needlessly incomplete and/or confusing. The minimum that I needed to do was:
Create ~/.config/fish/config.fish. This file can optionally be a softlink.
Add to it the line alias myalias echo foo bar.
Restart fish. To confirm the definition, try type myalias. Try the alias.