Symlink para o arquivo que ainda não existe

1

Atualmente, estou tentando limpar meu diretório inicial movendo arquivos como .vimrc , .bash_profile , etc. para um diretório .dotfiles em meu diretório inicial.

A ideia é usar links simbólicos para esses arquivos depois: ln -s ~/.dotfiles/.vimrc ~/.
Isso funciona bem, mas eu gostaria de automatizar esse processo escrevendo meu primeiro script bash e me deparei com alguns problemas.

O script atualmente se parece com algo assim:

#!//bin/bash
# Make script executable with: chmod u+x brew.sh

# Ask for the administrator password upfront.
sudo -v

# Keep-alive: update existing 'sudo' time stamp until the script has finished.
while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null &

# Create '.other'-folder
echo "--> ~/.other"
if [ -d ~/.other ];
then
  echo "Directory ~/.other exists..."
else
  echo "Creating directory ~/.other..."
  mkdir ~/.other
fi
echo ""

# TRASH
echo "--> ~/.Trash"
if [ -d ~/.Trash ];
then
  echo "Directory ~/.Trash does exists. Moving it to ~/.other..."
  mv ~/.Trash ~/.other/
else
  echo "Directory ~/.Trash doesn't exists. Creating it in ~/.other..."
  mkdir ~/.other/.Trash
fi

echo "Linking ~/.other/.Trash to ~/.Trash..."
ln -s ~/.other/.Trash ~/.
echo ""

# BASH_HISTORY
echo "--> ~/.bash_history"
if [ -a ~/.bash_history ];
then
  echo "File ~/.bash_history does exists. Moving it to ~/.other..."
  mv ~/.bash_history ~/.other/
else
  echo "File ~/.bash_history doesn't exists. Creating it in ~/.other..."
  touch ~/.other/.bash_history
fi

echo "Linking ~/.other/.bash_history to ~/.bash_history..."
ln -s ~/.other/.bash_history ~/.
echo ""

# BASH_SESSIONS
echo "--> ~/.bash_sessions"
if [ -d ~/.bash_sessions ];
then
  echo "Directory ~/.bash_history does exists. Moving it to ~/.other..."
  mv ~/.bash_sessions ~/.other/
else
  echo "Directory ~/.bash_history doesn't exists. Creating it in ~/.other..."
  mkdir ~/.other/.bash_sessions
fi

echo "Linking ~/.other/.bash_sessions/ to ~/.bash_sessions/..."
ln -s ~/.other/.bash_sessions ~/.
echo ""

# .LOCAL
echo "--> ~/.local"
if [ -d ~/.local ];
then
  echo "Directory ~/.local does exists. Moving it to ~/.other..."
  mv ~/.local ~/.other/
else
  echo "Directory ~/.local doesn't exists. Creating it in ~/.other..."
  mkdir ~/.other/.local
fi

echo "Linking ~/.other/.local/ to ~/.local/..."
ln -s ~/.other/.local ~/.
echo ""

# .CONFIG
echo "--> ~/.config"
if [ -d ~/.config ];
then
  echo "Directory ~/.config does exists. Moving it to ~/.other..."
  mv ~/.config ~/.other/
else
  echo "Directory ~/.config doesn't exists. Creating it in ~/.other..."
  mkdir ~/.other/.config
fi

echo "Linking ~/.other/.config/ to ~/.config/..."
ln -s ~/.other/.config ~/.
echo ""

Como você pode ver, o código é bem repetitivo, mas as primeiras são as primeiras. O código deve funcionar mais ou menos assim. Verifique se o arquivo (por exemplo, init.vim ) existe no meu diretório inicial. Se existir, mova-o para ~/.other ( arquivos não tão importantes ) ou para ~/.dotfiles ( arquivos importantes ). Se não existir, crie um arquivo (ou diretório) em ~/.dotfiles ou ~/.other . Symlink depois.

Até agora, a teoria. O problema é que, se o arquivo ainda não existe em meu diretório home - o script apenas cria um arquivo em ~/.dotfiles / ~/.other e vincula o nome no diretório inicial a ele. Isso não funciona na prática, já que alguns arquivos precisam de permissões específicas. Por exemplo, neovim não reconhece alguns arquivos se eles forem criados com este script e não é muito eficiente apenas criar os arquivos antes que eles sejam usados.

Existe uma maneira de corrigir isso (por exemplo, criando um link, sem criar o arquivo de destino? Eu tentei uma vez para vincular .bash_history a .other/.bash_history , o link funcionou bem, mas bash não conseguiu gravar em um arquivo não existente)? Seria ótimo se novos arquivos fossem criados no lugar correto e eu só precisasse especificar o lugar direito antes?

PS: Quando o arquivo já existe, o script funciona bem (ele apenas moveu o arquivo para o novo local e o vincula).

    
por LastSecondsToLive 25.01.2016 / 14:20

1 resposta

1

Uma reescrita para reduzir a duplicação

#!/bin/bash
# Make script executable with: chmod u+x brew.sh

# Ask for the administrator password upfront.
sudo -v

# Keep-alive: update existing 'sudo' time stamp until the script has finished.
while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null &

# Create '.other'-folder
echo "--> ~/.other"
mkdir -p ~/.other 2>/dev/null
echo ""

create_dir() {
    local pathname=$1 destination=$2 permissions=$3
    local dirname=$(basename "$pathname")

    echo "--> $pathname"
    if [ -L "$pathname" ] && [ "$(dirname "$(readlink "$pathname")")" = "$destination" ]; then
        echo "$pathname is already a symbolic link to $destination/$filename"
        return
    elif [ -d "$pathname" ]; then
        echo "Directory $pathname exists. Moving it to $destination..."
        mv "$pathname" $destination/
    else
        echo "Directory $pathname doesn't exist Creating it in $destination..."
        mkdir -p "$destination/$dirname"
    fi
    chmod "$permissions" "$destination/$direname"

    echo "Linking $destination/$dirname to $pathname ..."
    (
        cd "$(dirname "$pathname")"
        ln -s "$destination/$dirname" 
    )
    echo
}

create_file() {
    local pathname=$1 destination=$2 permissions=$3
    local filename=$(basename "$pathname")
    echo "--> $pathname"
    if [ -L "$pathname" ] && [ "$(dirname "$(readlink "$pathname")")" = "$destination" ]; then
        echo "$pathname is already a symbolic link to $destination/$filename"
        return
    elif [ -a "$pathname" ]; then
        echo "File $pathname exists. Moving it to $destination..."
        mv "$pathname" $destination/
    else
        echo "File $pathname doesn't exists. Creating it in $destination..."
        touch "$destination/$filename"
    fi
    chmod "$permissions" "$destination/$filename"

    echo "Linking $destination/$filename to ~/.bash_history..."
    (
        cd "$(dirname "$pathname")"
        ln -s "$destination/$filename"
    )
    echo ""
}

create_dir   ~/.Trash          ~/.other  755   # TRASH
create_file  ~/.bash_history   ~/.other  600   # BASH_HISTORY
create_file  ~/.bash_sessions  ~/.other  644   # BASH_SESSIONS
create_dir   ~/.local          ~/.other  755   # .LOCAL
create_dir   ~/.config         ~/.other  755   # .CONFIG

create_file  ~/.bashrc         ~/.dotfiles 644 # etc ...

Notas:

  • mkdir -p criará o diretório, se ele não existir
  • verifique se o diretório / arquivo já não é um link simbólico.
  • se arquivos específicos exigirem permissões específicas, não há escolha a não ser especificá-lo.
por 25.01.2016 / 15:18