What is the meaning of flag -s in this command? - terminal

I have met a command to load nvm environment in .zshrc, but I don't know what it exactly does with flag -s. I know that the square bracket is condition to check whether folder in this command exists or not. But don't know what -s does.
[ -s "/usr/local/opt/nvm/nvm.sh" ] && . "/usr/local/opt/nvm/nvm.sh" # This loads nvm
Does anyone know the flag -s in this command? Thank in advance.

[ is the same as test. Checking test's manpage:
-s file True if file exists and has a size greater than zero.
Update: Actually, using man '[' works, too.

Related

What does -f mean in bash

I was looking at how to use runit to run gunicorn. I was looking at the bash file and I don't know what -f $PID does in
#!/bin/sh
GUNICORN=/usr/local/bin/gunicorn
ROOT=/path/to/project
PID=/var/run/gunicorn.pid
APP=main:application
if [ -f $PID ]; then rm $PID; fi
cd $ROOT
exec $GUNICORN -c $ROOT/gunicorn.conf.py --pid=$PID $APP
Google is useless in this case because searching for flags is useless
Google is useless in this case because searching for flags is useless
Fortunately, the Bash Reference Manual is available online, at http://www.gnu.org/software/bash/manual/bashref.html. It's the first hit when you Google for "Bash manual". ยง6.4 "Bash Conditional Expressions" says:
-f file
True if file exists and is a regular file.
-f - file is a regular file (not a directory or device file)
Check this out for all file test operators:
http://tldp.org/LDP/abs/html/fto.html
The [ is the same as the command test which allows you to test certain things. Try help test to find out what the flags are. Things to be careful with are spaces - the [ needs a space after it.
-f checks if the file exists and is a regular file.
[ -f "$var" ]
Checks if $var is an existing file (regular file). Symbolic link passes this test too.

Shell script file existence test fails for broken symbolic link

This Bourne shell script fails to detect the existence of a broken symbolic link. It returns false and doesn't echo yet /usr/bin/firefox.real is a file that exists but as a broken symbolic link. Why?
FIREFOX="/usr/bin/firefox.real"
[ -e "$FIREFOX" ] && echo "exists"
The reason is that internally, bash will call fstat(), not lstat() when you test with -e, so it checks the file itself, not the symbolic link.
Use -h to check for existence of a link (even broken):
[ -h "$FIREFOX" ] && echo "exists"
As per man test:
-h FILE
FILE exists and is a symbolic link (same as -L)

Difference between file tests in Bash

I am troubleshooting an existing Bash script and in the script it has two tests:
if [ ! -s <file_location> ] ; then
# copy the file to the file_location
if [ -s <file_location> ] ; then
# operate on the file
fi
fi
According to the Bash Tutorial, -s tests if the file is not of zero size. Would it be better to replace the ! -s test with a -e ? I could understand the second, nested test being a -s but the first one looks like it could be replaced with -e. What is the advantage here of ! -s vs -e? Am I missing something?
If the file exists but is empty, -e would pass, but the file would likely be useless. Using ! -s ensures that the file is present and contains useful content.

chsh: Operation is not supported by the directory node when trying to change shell to zsh

I'm trying to install zsh as my shell.
I've used curl to get the files.
curl -L https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh | sh
But when it gets to changing the shell it gives me...
chsh: Operation is not supported by the directory node. Operation is not supported by the directory node.
chsh: no changes made
Any ideas why this would be happening would be appreciated.
First thing would be to try changing the shell from your command line...
chsh -s `which zsh`
I have the following code to deal with a similar situation (not being able to change login shell at a work cluster). It starts zsh from bash, with some care taken about it ("works for me")
# for hosts matching the silly name... start zsh from bash
if [[ `uname -n` == foo-[0-9][0-9].bar.foobar.bar ]]; then
if [[ -x `which --skip-alias zsh 2>/dev/null` ]]; then
if [ -z $ZSH_STARTED ]; then
export ZSH_STARTED="true"
zsh
fi
fi
fi

How to check for path expansion for executables

Like most makefiles, I have some bash scripts that use variables for executables. For example, $mysql_exec for /usr/bin/mysql. I would like to be able to say something like:
mysql_exec=mysql
to use $PATH or
mysql_exec=/usr/bin/mysql
to get an absolute location without $PATH. I also want to check to see if the executable is valid using something like this:
if [ ! -x $mysql_exec ] ...
However, this command:
if [ ! -x "mysql" ]; then print "oh oh"; fi
Actually prints "oh oh", even though mysql is in my $PATH. From the command-line, typing mysql has the same effect as typing /usr/bin/mysql. So, how do I get bash really check to see if $mysql_exec is an executable ($PATH and all)?
In Bash, you can use the built-in type -P to force a resolution against the PATH or type -p to show the path only if there's no alias or function by that name. Using type avoids calling an external such as which.
Something like this may do what you're looking for:
[ -x "$(type -p "$mysql_exec")" ]
whether you use
mysql_exec=mysql
or
mysql_exec=/usr/bin/mysql
which is a small program that checks $PATH for a program specified as an argument:
$ which mysql
/usr/bin/mysql
Another useful utility (that isn't installed on all systems but is included in GNU CoreUtils) is readlink. readlink can give you back a full and absolute path, without symlinks. For example:
$ cd ~me/bin
$ ln -s `which mysql` mysupersql
$ readlink -f mysupersql
/usr/bin/mysql
I often use a combination of both so I know that the path is both absolute and not a symlink:
mysql_exec=$(readlink -f `which mysql`)
if [ ! -x "$mysql_exec" ] ; then
...
To add to Kaleb's answer, you an also check if the file is a symlink using if [-L $file] and follow that symlink if you can't install readlink. The rest of the check though remains as the way Kaleb mentioned.

Resources