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}} ~/
}
}
@robrecord
Copy link

Thank you!

@autokludge
Copy link

Also worth noting ZDOTDIR can be set in /etc/zsh/zshenv if you want this set system-wide.
The ~/.zshenv file would no longer be required then.

#/etc/zsh/zshenv

export ZDOTDIR="$HOME"/.config/zsh

@stevencarpenter
Copy link

Also worth noting ZDOTDIR can be set in /etc/zsh/zshenv if you want this set system-wide. The ~/.zshenv file would no longer be required then.

#/etc/zsh/zshenv

export ZDOTDIR="$HOME"/.config/zsh

I could not make this work on macOS but it works great on arch(btw). If there is a way to get that to work on mac do share! I want my work mac and personal arch install to be as close as possible.

@autokludge
Copy link

I don't have first hand experience, this may help:
https://jdhao.github.io/post/zsh_startup_file/#zsh-startup-file-source-order

@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