How to create a alias in fish shell - fish

I try to create an alias for ls (should basically just map to ls -lah)
I've tried the following code, but it's not working:
function ls
ls -lah
end
funcsave ls
but when I call it I get this message:
The function 'ls' calls itself immediately, which would result in an infinite loop.
in function 'ls'
called on standard input

What you're looking for is the command command.
I would also recommend to pass any arguments (stored in $argv) to the aliased command.
So your example should be:
function ls
command ls -lah $argv
end
And to do all this with a simple command, you can simply use the alias command.
alias ls "command ls -lah"
Note that usually aliases will not get you the nice auto-complete suggestions that contribute to _fish_'s friendliness. This specific case is an exception because the function and the original command have the same way, but otherwise, here are two ways to get completions anyway:
You can use the complete command to tell fish that your alias uses the same completions as the aliased command.
The balias plugin
serves as an alternative to alias and does just that.
fish also offers an abbr command. It works slightly different and will actually expand the abbreviated command to the full command in the command line, and then fish will have no problem giving you all the auto-completion suggestions that it knows.

You need the command keyword. Also, pass the function's arguments to ls
function ls
command ls -lah $argv
end

If you need to make alias of ls, then the above answers are OK.
However, fish already has a command for ls -lah, which is la.

Related

Run command line via alias with zsh on MATLAB

I use the system/unix command on Matlab in order to run an external program via the command line. I want to execute it via an alias define in .zshrc on my computer. Unfortunately, the alias seems to be not available.
Example with ll
on a terminal: which ll gives ll: aliased to ls -lh
on Matlab: unix('ll') gives zsh:1: command not found: ll
I check if I used the right shell: unix('echo $SHELL') gives /usr/local/bin/zsh.
I have add setopt aliases in my .zshrc but it changes nothing. Is it possible to check which startup files is used when you open a non interactive shell?
The ~/.zshrc seems to be not loaded in the non interactive case. The solution consists in loaded aliases and added setopt aliases in ~/.zshenv. See this for instance.

How to put a comment after a IPython magic command

How can I put a comment at the end of an IPython magic command?
Eg, trying to use %cd:
%cd "dir" # comment
I want to change to directory dir but instead I get:
[Errno 2] No such file or directory: 'dir # comment'
It's not possible in general because IPython magic commands parse their own command lines.*
There are some magic commands where comments seem to work, but actually they're being handled in another way. For example:
%ls # comment works properly, but %ls is an alias to a shell command, so the shell is what's parsing the comment.
%automagic 0 # comment behaves like %automagic, toggling the setting instead of exclusively disabling it like %automagic 0 would do. It's as if the 0 # comment is all one string, which it ignores.
%run $filename # comment treats the comment as arguments, so ['#', 'comment'] ends up in sys.argv for $filename.
Workaround
You could call magic commands using exclusively Python syntax.
First get the running IPython instance with get_ipython():
ipython = get_ipython()
Then:
ipython.run_line_magic('cd', 'dir') # comment
Docs: InteractiveShell.run_line_magic()
Or for cell magics, you could go from this (which doesn't work):
%%script bash # comment
echo hello
to this:
ipython.run_cell_magic('script', 'bash', 'echo hello') # comment
Docs: InteractiveShell.run_cell_magic()
Another option, I suppose, is to run an entire cell, although, suppressing the output since it returns an ExecutionResult object:
ipython.run_cell('%cd dir'); # comment
Docs: InteractiveShell.run_cell()
* I'm not sure if this is documented explicitly, but it is documented implicitly under defining custom magics, and I found the clues in this GitHub issue: Allow comments after arguments in magic_arguments.
TL;DR: You cannot as things stand. This might or might not be an error in the implementation of %cd.
Until this is fixed, one way to avoid this is to use:
import os
os.chdir("dir") #some comment here
A second alternative is using bash commands.
However % is a magic command, not equivalent to a bash command. This is on purpose,
as it can change the current directory of the notebook.
This is not the same as e.g.
!cd dir #some comment here
Which will spawn a shell and execute the command there thus not changing the current directory. (You can verify using pwd before/after each command)
Note that if your goal is not to change the current jupyter notebook directory, you can issue multiple commands in one cell with the magic
%sh:
%%sh
cd dir #some comment here
ls #some more commands here
....
This command will spawn a shell and all bash commands will be executed there, so the current jupyter directory will not change.

In IPython every shell command is run by prefixing it with "!" but few commands run without that, What is the reason behind it?

In case of "ls" command it runs with and without the prefix "!". In case of "cat fileName" it's the same, but when you consider "wc -l fileName" it works only with "!" prefix.
When you combine cat and wc command "cat fileName | wc -l" executed successfully without "!" prefix.
I don't understand the logic behind this prefix "!" in ipython.
Thank you in advance
(I am new to python programming, if it sounds silly question please forgive me.)
IPython tries to make interactive programming as comfortable as possible. Some shell builtins like ls, cd or cat are basic commands to navigate in unix shells. IPython, as a "Python Shell" provides the same functionally for convenience. Along with features like colored output, etc.
The !command is for executing arbitrary shell code and is much more powerful. It can be used to run any command you can type in a normal shell and can also catch its output.
Compare ls with !ls. The former will print the content in your current directory with nice coloring. The latter will print the same list, but just plain text.
But note that you can do really cool things with !command:
files = !ls
for f in files:
print("I like this file:", f)
Which reads the output of ls into a python array files which you can use in your code just like any other array.
To sum up: if you just want to navigate, you usually use the standard commands, if available. If you need to capture the output or run programs you have to use the !command syntax.

How do I get Perl to run an alias I've defined in BASH?

I have a script that opens up different files at the same time.
My problem here is that when I run system() on the alias I've defined in bash which points to /home/user1/Software/nc, perl tells me that it can't execute the alias because there is no file/directory at the current location.
I know that the alias works because when I invoke it directly in a shell, it opens fine.
Funny enough, I can do system("firefox") within my script fine, but not the alias. How do I use this alias in this script without it breaking?
Perl won't run bash, it will execute the command directly. You can call
bash -c your_command
instead of calling the command itself in Perl.
As it is, this doesn't load your aliases. You need to open an interactive shell, as in #MortezaLSC's answer. There supposedly is a way of loading aliases correctly in a non-interactive shell, but I can't figure it out.
But why don't you just use the command you have aliased to directly in perl? The only reason I could see not to do this, is if your alias is going to change in the future, but you will still want to run whatever command it points to. This seems weird and dangerous to say the least.
Aliases are designed to reduce the typing you do if you invoke commands with the same options etc all the time. They're not all-purpose macros for bash. Bash has functions for doing more complicated stuff, but why would you want to call non-trivial bash code from a perl script? It doesn't seem like you really need this here. Keep the complexity, and the potential for modification and failure, in one place (the perl script).
See a couple of answers to similar questions:
https://unix.stackexchange.com/a/1499/41977
https://superuser.com/a/183980/187150
If you're smart, you made it so your alias is only defined for interactive shells, so you'll have to launch bash and specify that you want an interactive shell using -i.
system('bash', '-i', '-c', 'shell command');
Is it working?
system 'bash -i -c "your alias parameter"';

Which shell does a Perl system() call use?

I am using a system call to do some tasks
system('myframework mycode');
but it complains of missing environment variables.
Those environment variables are set at my bash shell (from where I run the Perl code).
What am I doing wrong?
Does the system call create a brand new shell (without environment variable settings)? How can I avoid that?
It's complicated. Perl does not necessarily invoke a shell. Perldoc says:
If there is only one scalar argument, the argument is checked for shell metacharacters, and if there are any, the entire argument is passed to the system's command shell for parsing (this is /bin/sh -c on Unix platforms, but varies on other platforms). If there are no shell metacharacters in the argument, it is split into words and passed directly to execvp , which is more efficient.
So it actually looks like you would have the arguments passed right to execvp. Furthermore, whether the shell loaded your .bashrc, .profile, or .bash_profile depends on whether the shell is interactive. Likely it isn't, but you can check like this.
If you don't want to invoke a shell, call system with a list:
system 'mycommand', 'arg1', '...';
system qw{mycommand arg1 ...};
If you want a specific shell, call it explicitly:
system "/path/to/mysh -c 'mycommand arg1 ...'";
I think it's not the question of shell choice, since environment variables are always inherited by subprocesses unless cleaned up explicitly.
Are you sure you have exported your variables?
This will work:
$ A=5 perl -e 'system(q{echo $A});'
5
$
This will work too:
$ export A=5
$ perl -e 'system(q{echo $A});'
5
$
This wouldn't:
$ A=5
$ perl -e 'system(q{echo $A});'
$
system() calls /bin/sh as a shell. If you are on a somewhat different box like ARM it would be good to read the man page for the exec family of calls -- default behavior. You can invoke your .profile if you need to, since system() takes a command
system(" . myhome/me/.profile && /path/to/mycommand")
I've struggled for 2 days working on this. In my case, environment variables were correctly set under linux but not cygwin.
From mkb's answer I thought to check out man perlrun and it mentions a variable called PERL5SHELL (specific to the Win32 port). The following then solved the problem:
$ENV{PERL5SHELL} = "sh";
As is often the case - all I can really say is "it works for me", although the documentation does imply that this might be a sensible solution:
May be set to an alternative shell that perl must use internally for executing "backtick" commands or system().
If the shell used by perl does not implicitly inherit the environment variables then they will not be set for you.
I messed with environment variables being set for my script on this post where I needed the env variable $DBUS_SESSION_BUS_ADDRESS to be set, but it wouldn't when I called the script as root. You can read through that, but in the end you can check whether %ENV contains your needed variables and if not add them.
From perlvar
%ENV
$ENV{expr}
The hash %ENV contains your current environment. Setting a value in "ENV" changes
the environment for any child processes you subsequently fork() off.
My problem was that I was running the script under sudo and that didn't preserve all my user's env variables, are you running the script under sudo or as some other user, say www-data (apache)?
Simple test:
user#host:~$ perl -e 'print $ENV{q/MY_ENV_VARIABLE/} . "\n"'
and if that doesn't work then you will need to add it to %ENV at the top of your script.
try system("echo \$SHELL"); on your system.