which command doesn't work on my computer - macos

In the past, we 'which' command to get the info of the relevant software on our computer, Like:
which python
which git
But now it seems don't work on my MacOS Mojave. Is there anything wrong with my setting?
New edition:
The result will turn out to be like this
AA:~ AA$ which python
/usr/bin/which: illegal option -- -
usage: which [-as] program ...
New edition2:
AA:~ AA$ type --all which
which is aliased to `alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
which is /usr/bin/which
AA:~ AA$ type -all python
python is /Users/AA/anaconda3/bin/python
python is /Users/AA/anaconda/bin/python
python is /usr/bin/python
AA:~ AA$

The alias is what causes the error message. Apparently the alias definition is simply erroneous for your system. It's not clear what defined this alias or why; it seems wrong on several levels, so I doubt it's part of the standard install.
You can remove the alias with unalias which; but I'm guessing it's defined in one of your startup files, and should be removed from there - after this point, it should be gone for good the next time you log in.
But anyway, you should not be using which - it's better to accustom yourself to the POSIX standard command type. It was introduced specifically to replace which but it's apparently still hard to eradicate the old command from people's minds.

For me, this was when something from a yarn global upgrade replaced my system's /usr/bin/which.
/usr/bin/which -> ../local/share/.config/yarn/global/node_modules/.bin/which
Since your error message is exactly the same as the text strings inside that program, it is possible that your issue is from a similar source.
console.error('which: illegal option -- ' + flag)
console.error('usage: which [-as] program ...')
"Fixed" with reinstalling which through the system's package manager (e.g. sudo dnf reinstall which). That may now interfere with whatever JavaScript package depended on that, but I plan on removing those globals, so I will not find out.
Better fix: I feel like my system is dirty now and needs all of its bin files checked... Comparing everything in /usr/local/share/.config/yarn/global/node_modules/.bin to see if it has an equivalent in /usr/bin seems like an easy enough way to look for other points of interference.
for x in $(ls /usr/local/share/.config/yarn/global/node_modules/.bin/*); do
ls -l /usr/bin/"$(basename "${x}")"
done
Then those can be checked against the system's package manager with commands like the following. Then reinstalled if needed.
sudo dnf info ...
sudo dnf provides ...
More:
Seems weird to me that it would allow clobbering existing system programs. At the very least, I would expect it to have used /usr/local/bin instead. That extra system and system-like package management seems to be why they have done away with yarn global in yarn 2 (berry).
I have different packages for sudo yarn global list and yarn global list. Maybe using sudo at some point was my mistake?
P.S. Thanks goes to #tripleee, I was unaware of type. I have seen various other ways of attempting to handle different which programs and different versions of which, along with alternatives like test (and others I have forgotten), but type looks worth trying as a replacement.
P.P.S. Annoying to find out that this OS is configured to run tab completion through which.
P.P.P.S. Yes, I know scripting with the output ls is a bad habit.

Related

How to provide shell completion with python a package? [duplicate]

I am writing a command line tool in python and using pip to distribute it. I have written some scripts (one for bash and one for zsh) to allow the tool to have tab completion. Is there a way to get pip to install these scripts when someone does a pip install?
For example:
I have a completion.bash file. When someone does
pip install mypackage
It will also source the bash file.
I'm pretty sure I can do this for linux and bash by putting the script in my data_files section in the setup.py script.
data_file=[
('/etc/bash_completion.d', ['bin/completion.bash'])
],
But how can I do this so it is platform and shell independent? I need it to work for mac/linux in both bash and zsh. If possible, even support windows.
Is this possible? And if so, how?
In case it matters, here is my bash script:
_foo_complete() {
COMPREPLY=()
local words=( "${COMP_WORDS[#]}" )
local word="${COMP_WORDS[COMP_CWORD]}"
words=("${words[#]:1}")
local completions="$(foo completer --cmplt=\""${words[*]}"\")"
COMPREPLY=( $(compgen -W "$completions" -- "$word") )
}
complete -F _foo_complete foo
I am currently installing it by just running source completion.bash
You are asking several different questions.
First, there's no cross-platform or cross-shell solution for defining custom shell-completions. The one you posted works for bash, but in tcsh, for example, you use tcsh's complete command, which works differently than bash's.
Second, sourcing the files which contain those completion-definitions at the time of pip install wouldn't do much good. The completions might work in that very session, but what you probably want is for them to take effect in future sessions (i.e. shell invocations) as well. For that, your files would have to be sourced each time the shell starts (e.g. from within user's .bashrc, in case of bash).
This measn that "installing" your files simply means placing them somewhere, and suggesting the users should source them from their respective dot-rc file. Even if you could, you shouldn't try to "force" it. Give your users the option to add that to their dot-rc file if they want.
The best approach would probably be to include in your package a completion-definitions file per supported shell, e.g. complete.bash, complete.tcsh, and god knows what for windows (sorry, I'm not a windows user).

mkfs.vfat and mkfs.ext3 in CYGWIN

I'm running a bash script in the Embedded Command Line that comes with Quartus II. The bash script was sent to me from someone using linux and I was able to get most of the script to work(removing sudo, changing path, etc.). The only two commands that are still giving me errors are mkfs.ext3 and mkfs.vfat. Are these tucked away somewhere in cygwin that I need to add a path or is there another workaround? I've read some people use mkdofsf but cygwin doesn't appear to have that either.
UPDATE:
Tried using /sbin/mkfs - t vfat and /sbin/mkfs -t ext3 but this left me with a similiar error where mkfs.vfat and mkfs.ext3 were not found.
UPDATE 2: Installed e2fsprogs to solve the error with mkfs.ext3 but this doesn't solve the vfat formatting issue.
These are part of the package e2fsprogs which is available in Cygwin. I've never tried these commands, assuming that access to the raw devices would be blocked by Windows. But I see that cfdisk seems to work. It at least starts up, anyway. So, maybe it is doable.
If they don't work on raw devices, if your scripts are creating file systems on a file or can be modified to do that, that should probably work.
Anyway, e2fsprogs is what you need, but be careful here. Whenever you start making or editing file systems, you have the opportunity to really screw up your system. Just be attentive to what the script is doing, and don't blindly go forward.

Error message on Terminal launch [duplicate]

This question already has an answer here:
How to restore .bash_profile on a mac? None of my unix terminal are working [closed]
(1 answer)
Closed 2 years ago.
I receive this error message each time I launch terminal:
-bash: =/usr/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin: No such file or directory
You have recently edited one of your shell's startup files and introduced an error.
Probably, ls -lart ~/.bashrc ~/.bash_profile ~/.profile will indicate which one -- if one or more is missing, that's no concern, we just want to see which one out of these you have edited recently. Examine the time stamps and try to remember what you did to change one of these files.
The error probably looks something like
$oopsPATH=/usr/local/bin:$PATH
where you meant to say
PATH=/usr/local/bin:$PATH
but without access to your files, we can't know what exactly is supposed to be there, or how you messed it up.
See also https://askubuntu.com/questions/198730/how-to-restore-bashrc-file/198740#198740
In the common case where you have messed up your PATH so that ls and other commands are unavailable (bash: ls: command not found), you can use the full path (/bin/ls pro ls, etc; though obviously, you have to know the correct path) at least until you can restore your configuration.
PATH=/usr/local/bin:/usr/bin:/bin
is probably a good crutch until you can find the correct default for your OS. You can type that at the prompt, or put it in one of your shell's startup files and start a new shell.
On many platforms, you can find the default user dot files in /etc/skel so if that's present (which unfortunately will not be true for Mac OS, but should be there on most Linuxes):
cp -b /etc/skel/.bash_profile $HOME/
will replace your (presumably broken beyond repair) .bash_profile with the system default one. (Omit the -b option if your OS doesn't have it, but then you'll want to back up your file manually before replacing it.)
Update: This fragment near the top of your .bash_profile is erroneous:
#loginPath
=/usr/local/bin:$PATH
Just take it out; it doesn't seem to do anything useful. There seem to be multiple additional fragments from the MacPorts installer which look wrong, too, but they are just comments. (Perhaps somehow they shouldn't be?)
It seems that you are missing a necessary PATH and that is why it is saying no such file or directory. If, for example, you get this error message when typing in python, it would mean either that (1) python isn't installed; or (2) python isn't on your system path.

Too many bash initialization files?

I just installed GMT4 (Generic Mapping Tools) from MacPorts and have run into some serious issues with terminal...
When using the ls command in terminal I get the following:
-bash: ls: command not found
To fix this I've tried many things that I read many different places online. I've changed the following files to include /usr and /bin:
~/.bashrc
~/.bash_profile
~/.profile
Doing so gave me back the sudo command which I had previously lost.
However, I still am not able to use ls in a new terminal window without manually exporting the path("new session"). This has been causing problems when I'm running shell scripts that use system functions. So I'm starting to wonder what exactly those three files do and if maybe having three files doing the same thing is causing them to interfere with one another. If anyone can tell me where I need to add these PATHS that would be great; I dunno, maybe I can delete one of these files or something ELSE is conflicting. Right now I just run " export PATH=$PATH:/usr" in each new terminal window and it works for that session.
I'm running Mac OS X 10.6 on a early 2011 MacBook Pro with 4GB of RAM.
Background for those who are interested:
My end goal is to use Relax to model viscoelastic relaxation in a mid-oceanic ridge system to come up with some sort of constitutive law or power-relation between slip magnitude and the location of greatest tensional stress in the lithosphere due to normal faulting.
The Bash manual actually explains these files fairly thoroughly. However, the manual does not describe how these mechanisms are usually used in practice. What follows is a brief, abridged version of what is common best practice.
.profile is read at login by both sh and bash.
.bashrc is read by non-login Bash shells. By convention, .bash_profile sources .bashrc in turn.
.bash_profile is read at login by Bash. If this file exists, .profile is not read. By convention, .bash_profile should source .profile if it exists.

How can I make bash deal with long param using "getopt" command in mac?

I want to make my bash script deal with long parameters. I found getopt, but it isn't supported in OS X. Can anyone tell me why getopt was implemented by BSD, but not GNU?
I tried building getopt in GNU C lib, but it failed for my poor skills with Linux.
Did anyone do this work?
There is a brew bottle for getopt.
Just run brew install gnu-getopt.
You can either specify the path for it like
/usr/local/Cellar/gnu-getopt/1.1.6/bin/getopt
Or use brew link --force gnu-getopt so it will be linked in /usr/local/bin/
Just be aware that forcing linking might be corrupting your system (as it replaces the system getopt by the gnu one).
See maybe later answer suggesting to define FLAGS_GETOPT_CMD (though few comments state issues with it).
I recommend using Homebrew to install gnu-getopt and then adding $FLAGS_GETOPT_CMD to your ~/.bash_profile file to specify the cmd path for getopt, pointing at the homebrew location, like so:
brew install gnu-getopt
Then follow directions from brew to add to your local path:
sudo echo 'export PATH="/usr/local/opt/gnu-getopt/bin:$PATH"' >> ~/.bash_profile
Then you can add FLAGS_GETOPT_CMD:
sudo echo 'export FLAGS_GETOPT_CMD="$(brew --prefix gnu-getopt)/bin/getopt"' >> ~/.bash_profile
Open a new terminal, or run . ~/.bash_profile in existing terminal to load changes
Run echo $FLAGS_GETOPT_CMD to confirm it was actually set in your console
It's generally a better idea to use getopts instead, and stick with short options. You can see getopts in action in this StackOverflow Q&A. Short options are more standard throughout OSX command line tools, and consistency is a good thing.
Also, getopts is built in to bash, so it's definitely available in OSX, as well as every other platform that can run bash.
Note that there is a getopt is also available in OSX. From Terminal, type man getopt to see its documentation. It doesn't support long options. This is a good reason not to use long options when you're writing tools to run on OSX.
If you want to do this anyway, you can install getopt from macports. Alternately, if you want better portability, you can roll your own long argument handling.
Post some code, and we'll help debug it.

Resources