Delete all target links and files before running GNU Stow

GNU Stow does not run properly if the target files already exist. So, i have written a script which will first delete all files and links in the target then run Stow.


fd --hidden --ignore-file .gitignore --base-directory="$HOME/.dotfiles/.common-dotfiles" --type l --type f | sd ^. $HOME | xargs -I{} rm {}
stow --no-folding --target="$HOME" --dir="$HOME/.dotfiles" --restow .common-dotfiles

But my gut is telling me that this is not a good idea. What am I missing here? Is there any risk running this script? How can I improve this script?

Update 1:

GNU Stow create an exact copy of the source directory structure in the target. So, I first take the directory structure of the source. Change the path to match the target. Then run xargs -I{} rm {} on it.

I have broken the output of the pipe bellow.

First I am searching all the files in the $HOME/.dotfiles/.common-dotfiles directory.

% fd --hidden --ignore-file .gitignore --base-directory="$HOME/.dotfiles/.common-dotfiles" --type l --type f

Now I am modifying the path using piping the output of previous command to sd ^. $HOME to match the target directory.

% fd --hidden --ignore-file .gitignore --base-directory="$HOME/.dotfiles/.common-dotfiles" --type l --type f | sd ^. $HOME

So, now I am no longer deleting files in $HOME/.dotfiles/.common-dotfiles but in $HOME.

Asked By: Ahmad Ismail


I have done some research and found the answer in the documentation.


Warning! This behaviour is specifically intended to alter the contents of your stow directory. If you do not want that, this option
is not for you.

When stowing, if a target is encountered which already exists but is a plain file (and hence not owned by any existing stow package),
then normally Stow will register this as a conflict and refuse to
proceed. This option changes that behaviour so that the file is moved
to the same relative place within the package’s installation image
within the stow directory, and then stowing proceeds as before. So
effectively, the file becomes adopted by the stow package, without its
contents changing.

This is particularly useful when the stow package is under the control of a version control system, because it allows files in the
target tree, with potentially different contents to the equivalent
versions in the stow package’s installation image, to be adopted into
the package, then compared by running something like ‘git diff …’
inside the stow package, and finally either kept (e.g. via ‘git commit
…’) or discarded (‘git checkout HEAD …’).

So, what I should do is:

git checkout HEAD
stow --adopt --stow .common-dotfiles
git checkout HEAD
stow --restow .common-dotfiles

If we need to keep some changes, then we can run git diff, and resolve the merge conflicts after stow --adopt command.

In the above commands i use restore . instead of checkout HEAD.

Answered By: Ahmad Ismail

I use Ansible and shell scripting to check for conflicting target files in my $HOME folder and delete them before running GNU Stow. I explain my approach here.

Answered By: NebulaSurfer
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.