The location of the sourced script is not available unless you are using a shell that offers extensions to the POSIX specification. You can test this with the following snippet:
env -i PATH=/usr/bin:/bin sh -c '. ./included.sh' | grep included
where included.sh
contains
echo "$0"
set
In bash, the name of the sourced script is in $BASH_SOURCE
. In zsh (in zsh compatibility mode, not in sh or ksh compatibility mode), it's in $0
(note that in a function, $0
is the function name instead). In pdksh and dash, it isn't available. In ksh93, this method doesn't reveal the solution, but the full path to the included script is available as ${.sh.file}
.
If requiring bash or ksh93 or zsh is good enough, you can use this snippet:
if [ -n "$BASH_SOURCE" ]; then
this_script=$BASH_SOURCE
elif [ -n "$ZSH_VERSION" ]; then
setopt function_argzero
this_script=$0
elif eval '[[ -n ${.sh.file} ]]' 2>/dev/null; then
eval 'this_script=${.sh.file}'
else
echo 1>&2 "Unsupported shell. Please use bash, ksh93 or zsh."
exit 2
fi
You can try to guess the location of the script by looking at what files the shell has open. Experimentally this seems to work with dash and pdksh but not with bash or ksh93 which at least for a short script have closed the script file by the time they get around to executing it.
open_file=$(lsof -F n -p $$ | sed -n '$s/^n//p')
if [ -n "$open_file" ]; then
# best guess: $open_file is this script
fi
The script may not be the file with the highest-numbered descriptor if the script is sourced inside a complex script that has been playing with redirections. You may want to loop through the open files. This is not guaranteed to work anyway. The only reliable way to locate a sourced script is to use bash, ksh93 or zsh.
If you can change the interface, then instead of sourcing your script, have your script print out a shell snippet to be passed to eval
in the caller. This is what scripts to set environment variables typically do. It allows your script to be written independently of the vagaries of the caller's shell and shell configuration.
#!/bin/sh
FOO_DIR=$(dirname -- "$0")
cat <<EOF
FOO_DIR='$(printf %s "$FOO_DIR" | sed "s/'/'\\''/g")'
PATH="\$PATH:$FOO_DIR/bin";
export FOO_DIR PATH
EOF
In the caller: eval "`/path/to/setenv`"
Zsh stores input lines (possibly with time information) in the file indicated by the variable HISTFILE
. This should be an absolute file name (otherwise it will be interpreted relative to whatever directory is current at the time).
Zsh has no built-in default value for HISTFILE
. The zsh distribution comes with a setup wizard for new users which has the value ~/.histfile
built in, so this is what zsh users get by default. Oh-my-zsh comes with HISTFILE=.zhistory
preset. So it looks like you tried zsh both with the default setup and with oh-my-zsh. Check your .zshrc
(or the file dates) to see which one you're currently using.
How zsh opens the file, and therefore what happens if it is a symbolic link, depends on several options.
- If one of the options
append_history
(set by default), inc_append_history
or share_history
is set, or when the history is saved explicitly with fc -AI
, zsh appends to the existing file.
Note that even under these settings, zsh occasionally overwrite the file as described below to trim it down to size.
- Otherwise, if the option
hist_save_by_copy
is set (it's set by default since zsh 5.0, but does not exist in 4.2), zsh writes a temporary file then moves it in place when complete. In this case, if the history file was a symbolic link, the new file replaces the symbolic link.
- Otherwise zsh overwrites the existing file in place.
Rather than point zsh to a symbolic link, set HISTFILE
to wherever you want the history file to be.
How many lines of history are kept is configured through the variables HISTSIZE
and SAVEHIST
. HISTSIZE
is the maximum number of lines that are kept in a session and SAVEHIST
is the maximum number of lines that are kept in the history file.
To get some history saved at all, you need to set both HISTFILE
and SAVEHIST
, as the default value of SAVEHIST
is 0. You may want to increase HISTSIZE
as well (as of zsh 5.0, the default is only 30).
Best Answer
From the zsh manual (
zshoptions(1)
):