Skip to content

Instantly share code, notes, and snippets.

@romkatv
Last active June 4, 2024 17:53
Show Gist options
  • Save romkatv/ecce772ce46b36262dc2e702ea15df9f to your computer and use it in GitHub Desktop.
Save romkatv/ecce772ce46b36262dc2e702ea15df9f to your computer and use it in GitHub Desktop.
Migrate zsh dotfiles from the home directory to another directory on the same machine
# This command moves your zsh dotfiles (.zshrc, .zsh_history, etc.)
# from the home directory to ~/.config/zsh. It's been verified to
# work correctly if you are using zsh4humans. With other zsh configs
# your mileage may vary.
#
# How to:
#
# 1. Close all terminals except one.
# 2. Copy-paste this command into the only remaining terminal.
() {
emulate -L zsh -o err_return -o no_unset -o xtrace
# The new ZDOTDIR relative to $HOME. You might want to
# change this value before running the script.
local -r zdotdir='.config/zsh'
# The absolute path to the new ZDOTDIR.
local -r dstdir=~/$zdotdir
# Create the new ZDOTDIR if it does not exist.
command mkdir -p -- $dstdir
# The list of files to be moved from $HOME to the new ZDOTDIR.
local -r srcs=(
~/.{zshenv,zprofile,zshrc,zlogin,zlogout}{,.zwc}(N)
~/.p10k*.zsh{,.zwc}(N)
~/.zsh_history(N)
)
# Check that all source files are regular files.
() { (( $# == $#srcs )) } ${^srcs}(.)
# Check that ~/.zshenv exists.
[[ $srcs[1] == ~/.zshenv ]]
# Copy the files to the new ZDOTDIR.
command cp -p -- $srcs $dstdir/
{
# Create ~/.zshenv with the new content.
print -rC1 -- "ZDOTDIR=~/${(q-)zdotdir}" 'source -- "$ZDOTDIR"/.zshenv' >~/.zshenv
if (( $#srcs > 1 )); then
# Delete all files we've copied except for ~/.zshenv.
command rm -f -- $srcs[2,-1]
# Verify that the files have been deleted.
() { (( ! $# )) } ${^srcs[2,-1]}(N)
fi
# Unset ZDOTDIR if it's set.
local ZDOTDIR
unset ZDOTDIR
# Replace the current process with a new instance of zsh.
exec zsh
} always {
# If anything goes wrong, attempt to restore the original files in $HOME.
command cp -p -- $dstdir/${^${(@)srcs:t}} ~/
}
}
@stevencarpenter
Copy link

My experience is that it should work, but it doesn't. I am setting my XDG_* and ZDOTDIR environment variables in /etc/zsh/zshenv on both arch and mac and it only works on arch which just doesn't make sense, but that's what I am observing. I worked around it by generating a ~/.zshrc in my setup script since it doesn't fit the simplicity of my gnu stow setup for everything else. Certainly not the end of the world, but it would be nice if it was all universal.

@autokludge
Copy link

Linked article suggests /etc/zshenv, not /etc/zsh/zshenv. Still painful to work around differences regardless.

@stevencarpenter
Copy link

Oh good eye, I glossed over that! Still different though. Definitely very on brand for Apple...

@knottio
Copy link

knottio commented Jun 4, 2024

Oh good eye, I glossed over that! Still different though. Definitely very on brand for Apple...

Surprisingly, it's not actually Apple in this case. Arch changes it from the default.

@stevencarpenter
Copy link

Oh good eye, I glossed over that! Still different though. Definitely very on brand for Apple...

Surprisingly, it's not actually Apple in this case. Arch changes it from the default.

Woah, I'm wrong again! I do agree with the way arch handles it though. I like being able to have a system wide configuration. It's been useful in the past with shared machines instead of having to configure something for every user.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment