tmux + fish shell; conf being sourced twice - tmux

When I start tmux, my ~/.config/fish/config.fish seems to be sourced again. This means any set PATH foo $PATH statements in my config get executed again, which leads to my PATH variable having duplicate entries in it. This isn't drastic, but it is annoying to ECHO path. when it is so long
How can I prevent this problem?
EDIT: the only fish related entires in my tmux file are
#fix vim
set -g default-shell $SHELL
set -g default-command "reattach-to-user-namespace -l ${SHELL}"
set -g default-command 'reattach-to-user-namespace $SHELL --login'

The ~/.config/fish/config.fish config file is read by every new fish instance. There are several ways to achieve what you're asking. One option is to always set PATH from scratch. That is, don't modify the existing path by appending or prepending to it but instead set it to exactly what you want for a given machine. Something along the lines of
set -gx PATH $HOME/bin /usr/local/bin /usr/bin/ /bin
test -d /opt/X11/bin
and set PATH $PATH /opt/X11/bin
Another option is to add directories only if they aren't already in the path:
contains /usr/local/bin $PATH
or set PATH /usr/local/bin $PATH
Or only do the modification if not inside a tmux session:
if not set -q TMUX
set PATH /argle/bargle $PATH
end

Related

Change tmux default to zsh

When tmux opens, I would like it to use zsh instead of bash by default. How would I accomplish this?
From man tmux:
default-shell path
Specify the default shell. This is used as the login shell for new windows when the default-command option is set to empty, and must
be the full path of the executable. When started tmux tries to set a default value from the first suitable of the SHELL environment
variable, the shell returned by getpwuid(3), or /bin/sh. This option should be configured when tmux is used as a login shell.
So, in your tmux.conf:
# set shell
set -g default-shell /bin/zsh
and if you want you can add default command each time, when we start a new window:
# Retach userspaces
set -g default-command "reattach-to-user-namespace -l zsh"
You probably want zsh to be your default shell for most things, then (but this will not apply to cron). The following will make zsh your default shell, and you should then not need to tell tmux anything.
chsh -s /usr/bin/zsh
Note that some OSs still use /bin/zsh as the path to zsh.
If you prefer to set it individually for a session, but not for other (future) sessions, you can use
tmux new-session /bin/zsh \; set default-shell /bin/zsh

Tmux: missing tmux config file?

Just installed tmux via homebrew and I'm trying to locate the system-wide tmux configuration file. The man pages state that the system-wide file should be located in /etc/tmux.conf, but for some reason, it is not there. Where is the default tmux.conf file located?
Note: Currently running OSX Mavericks
As far as I can tell the tmux installed via homebrew does not have a system wide conf file. If you did need one you could add your own at /etc/tmux.conf. However, I would wonder the need for this. I place my config in ~/.tmux.conf and everything is very happy.
There is a /usr/local/Cellar/tmux/1.8/etc directory but it houses the bash completion scripts. I also checked usr/local/etc it it to did not have an installed config.
I'm pretty confident at this point that the tmux installer via homebrew does not install it's own system wide config file instead leaving that as an exercise for the sys admin if such a feature was required.
By default tmux doesn't have a system-wide config that is editable. It's complied into the program.
Use these commands to list out the compiled defaults, then make your own file with it for your user.
tmux list-keys # show current bindings
tmux show-options -s # show current server options
tmux show-options -g # show current global session options
tmux show-options # show current session options
tmux show-options -gw # show current global window options
tmux show-options -w # show current window options
With tmux 1.7, show-options can also show you the value of a single option (prior versions can only list all the options from the specified class):
tmux show-options -gw window-status-format
You should find something useful in:
/usr/share/doc/tmux/examples
recent versions of tmux only have the examples conf files, it's not an OSX issue, just new default tmux packaging. So you can use any of those doing something like:
$cp /usr/share/doc/tmux/examples/someconffile.conf ~/.tmux.conf
that should do it.
from the man tmux page:
-f file Specify an alternative configuration file. By default, tmux loads the system configuration file from /usr/local/etc/tmux.conf, if present, then looks for a user configuration file at
~/.tmux.conf.
If there is no file, you can just create one using touch ~/.tmux.conf and write whatever you want.
Alon Gouldman's answer worked for me. Just to add to it:
I had this issue when working on Ubuntu 20.04.
Here's how I solved it:
Firstly, if do not find any configuratio file for tmux in your home directory, then create one inside your home (~) directory using the command:
touch ~/.tmux.conf
Next, to make the file to be always available whenever you start a Tmux session add the file to either the ~/.bash_profile, ~/.bash_login, and ~/.profile file. It should be added at the bottom of the file:
source "$HOME/.tmux.conf"
Here's an example:
# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.
# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
#umask 022
# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
PATH="$HOME/.local/bin:$PATH"
fi
source "$HOME/.tmux.conf"
Note: The ~/.bash_profile file takes the first precedence, then the ~/.bash_login file as the second precedence, and then the ~/.profile file as the last precedence.
That's all.
I hope this helps
"I will take a crack at it. Here are some solutions off the top of my head. I do not run Mac but I run RH, Debian, FreeBSD, and Solaris, CYgwin and other stuff.
My understanding which is taken straight from man tmux. The -f flag will specify an alternative configuration file. By default, tmux loads the system configuration file from /etc/tmux.conf, if present, then looks for a user configuration file at ~/.tmux.conf. The configuration file is a set of tmux commands which are executed in sequence when the server is first started.
#!/usr/bin/env bash
unset temporary_array_tmp ; declare -a temporary_array_tmp
temporary_array_tmp=(/etc/tmux.conf ~/.tmux.conf)
# The next line creates an empty global and personal configuration file,
# if it individually does NOT exists.
for i_tmp in "${temporary_array_tmp[#]}" ; do
[[ ! -f "${i_tmp}" ]] && \
touch "${i_tmp}" && \
echo -en "I created an empty tmux configuration file # ${i_tmp}. " && \
echo -e "You need to add configuration settings to ${i_tmp} ." || \
echo -e "The tmux configuration file ${i_tmp} already exists."
done
# After you add configuration settings, then you need
# to tell tmux to reload the files.
for i_tmp in "${temporary_array_tmp[#]}" ; do
[[ -f "${i_tmp}" ]] && \
tmux source-file "${i_tmp}" && \
echo -e "${i_tmp} The tmux configuration file ${i_tmp} is loaded." || \
echo -e "The tmux configuration file ${i_tmp} is NOT loaded."
done
unset temporary_array_tmp
Mentionable Notes
Next you can find tmux directories and/or files using find. For example:
find ~/ /etc /usr -iname *tmux*

How to execute bash script from any location?

In UNIX, I read that moving a shell script to /usr/local/bin will allow you to execute the script from any location by simply typing "[scriptname].sh" and pressing enter.
I have moved a script with both normal user and root permissions but I can't run it.
The script:
#! bin/bash
echo "The current date and time is:"
date
echo "The total system uptime is"
uptime
echo "The users currently logged in are:"
who
echo "The current user is:"
who -m
exit 0
This is what happens when I try to move and then run the script:
[myusername#VDDK13C-6DDE885 ~]$ sudo mv sysinfo.sh /usr/local/bin
[myusername#VDDK13C-6DDE885 ~]$ sysinfo.sh
bash: sysinfo.sh: command not found
If you want to run the script from everywhere you need to add it to your PATH. Usually /usr/local/bin is in the path of every user so this way it should work.
So check if in your system /usr/local/bin is in your PATH doing, on your terminal:
echo $PATH
You should see a lot of paths listed (like /bin, /sbin etc...). If its not listed you can add it. A even better solution is to keep all your scripts inside a directory, for example in your home and add it to your path.
To add a directory in your path you can modify your shell init scripts and add the new directories, for example if you're usin the BASH shell you can edi your .bashrc and add the line:
PATH=$PATH:/the_directory_you_want_to_add/:/another_directory/
This will append the new directories to your existing PATH.
You have to move it somewhere in your path. Try this:
echo $PATH
I bet /usr/local/bin is not listed.
I handle this by making a bin directory in my $HOME (i.e. mkdir ~/bin) and adding this to my ~/.bashrc file (make the file if you don't already have one):
export PATH=~/bin:$PATH
This may seem silly to mention, but did you make sure it is executable? Did you chmod +x script.sh? Does the shell script have the correct path to it's shell at the top (i.e #!/bin/bash)? Also, are you using UNIX or LINUX or FreeBSD? (last question is important)
To run executable from any directory:
1)Make a bin directory under your home directory and mv your executable scripts into it.
[root#ip9-114-192-179 ~]# cd /home
[root#ip9-114-192-179 home]# mkdir bin
[root#ip9-114-192-179 home]#ls
bin cloud-init-0.7.4-10.el7.noarch.rpm cloud-user epel-release-7-11.noarch.rpm
2)Move your executable scripts in bin direcoty.
mv preeti.sh /home/bin
3)Now add it to your path variable.And source it.
[root#ip9-114-192-179 ~]# echo 'export PATH="$PATH:/home/bin"' >> /etc/profile
[root#ip9-114-192-179 ~]# source /etc/profile
[root#ip9-114-192-179 ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/home/bin
4)Check if that path is added in path variable.
[root#ip9-114-192-179 ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/home/bin
5)Verify if script is running from any random directory.

How to always have the same current directory in VIm and in Terminal?

I would like to my terminal current directory follows my VIM one.
Example:
In TERMINAL:
> pwd
=> /Users/rege
> vim
Then in VIM
:cd /Users/rege/project
<Ctrl-z>(for suspend)
In terminal
> pwd
=> /Users/rege/project
I`m using MacOS, zsh, tmux.
I need this because when Im trying to use tags in VIM, tags are check in project from my terminal directory not vim one.
So I need to change terminal current directory always when I change VIM current directory.
What kind of command do you issue in your shell after you suspend Vim? Isn't Vim's :!command enough?
With set autochdir, Vim's current directory follows you as you jump from file to file. With this setting, a simple :!ctags -R . will always create a tags file in the directory of the current file.
Another useful setting is set tags=./tags,tags;$HOME which tells Vim to look for a tags file in the directory of the current file, then in the "current directory" and up and up until it reaches your ~/. You might modify the endpoint to suit your needs. This allows you to use a tags at the root of your project while editing any file belonging to the project.
So, basically, you can go a long way without leaving Vim at all.
If you really need to go back to the shell to issue your commands, :shell (or :sh) launchs a new shell with Vim's current directory. When you are done, you only have to $ exit to go back to Vim:
$ pwd
/home/romainl
$ vim
:cd Projects
:sh
$ pwd
/home/romainl/Projects
$ exit
In bash or zsh and on Unix you can do this: current working directory of the process is represented in /proc/{PID}/cwd as a symlink to a real directory. Speaking about zsh the following code will do the job:
function precmd()
{
emulate -L zsh
(( $#jobstates == 1 )) || return
local -i PID=${${${(s.:.)${(v)jobstates[1]}}[3]}%\=*}
cd $(readlink /proc/$PID/cwd)
}
. Note: with this code you won’t be able to pernamently switch directories in terminal anymore, only in vim or for duration of one command (using cd other-dir && some command).
Note 2: I have no idea how to express this in bash. The straightforward way is to get PIDs of all children of the shell (using ps --ppid $$ -o CMD), filter out the ps process (it will be shown as a child as well), check that there is only one other child and use its PID like in the last line above. But I am pretty sure there is a better way using some shell builtins like I did with zsh’s $jobstates associative array. I also don’t remember what is the analogue of precmd in bash.
Another idea would be making vim save its current directory into some file when you do <C-z> and make shell read this in precmd:
" In .vimrc:
function s:CtrlZ()
call writefile([fnamemodify('.', ':p')], $CWDFILE, 'b')
return "\<C-z>"
endfunction
nnoremap <expr> <C-z> <SID>CtrlZ()
# In .zshrc
function vim()
{
local -x CWDFILE=~/.workdirs/$$
test -d $CWDFILE:h || mkdir $CWDFILE:h
vim $#
}
function precmd()
{
local CWDFILE=~/.workdirs/$$
test -e $CWDFILE && cd "$(cat $CWDFILE)"
}
. It should be easier to port above code to bash.
you can open a new terminal like this
:!xterm -e bash -c "cd %:p:h;bash" &
actually I write this in my .vimrc
nmap <F3> :!xterm -e bash -c "cd %:p:h;bash" &<CR> | :redraw!
For bash users coming by:
Vim: Save pwd at <c-z> (with map and getpwd()).
Bash: Before prompt command, goto directory indicated by vim with PROMPT_COMMAND.
.bashrc
PROMPT_COMMAND='read -r line 2>/dev/null </tmp/cd_vim'\
'&& > /tmp/cd_vim && cd ${line##\r};'$PROMPT_COMMAND
vimrc
function! s:CtrlZ() call writefile([getcwd(),''], '/tmp/cd_vim', 'b')
return "\<C-z>"
endfunction
nnoremap <expr> <C-z> <SID>CtrlZ()
This is ZyX answer edited for bash https://stackoverflow.com/a/12241861/2544873

How can I copy entire directories and exclude specific files in Unix

I have a Unix batch script that copies the contents of one directory (call it dir A) to another (call it dir B).
Here is the copy statement I have currently.
cp -urL /path/to/dir/A /path/to/dir/B
However, this statement copies over hidden files.
How can I exclude any and all hidden files from being copied over?
Put star (*) in to copy but ignore hidden files
cp -urL -r /path/to/dir/A/* /path/to/dir/B
If using bash as your shell, unset the dotglob shell option.
From man bash
dotglob If set, bash includes filenames beginning with a '.' in the
results of pathname expansion.
#!/bin/bash
shopt -u dotglob
cp -urL /path/to/dir/A /path/to/dir/B

Resources