makefile : foreach error - bash

I have this in my makefile,
rcFiles = .vim .vimrc .gitconfig .hgrc .screenrc .Xresources .dircolors .bashrc .ctags .bash_completion.d
install:
#$(foreach f,$(rcFiles), [ -f $(HOME)/$f ] || ln -v -s $(PWD)/$f $(HOME)/ ; )
if .bashrc exits and I try
make install
I get
ln: creating symbolic link `/home/user/.vim': File exists
ln: creating symbolic link `/home/user/.bash_completion.d': File exists
and the process is aborted.
why no prevented this problem the conditional?

ln -sfvn source target
The --force flag makes it replace an existing link
The --no-dereference avoids creating 'subdirectory' links for links to directory, if the link existed already (useful for the .bash_completion.d and .vim dirs)
rcFiles = .vim .vimrc .gitconfig .hgrc .screenrc .Xresources .dircolors .bashrc .ctags .bash_completion.d
install:
#$(foreach f,$(rcFiles), [ -f $(HOME)/$f ] || ln -v -f -n -s $(PWD)/$f $(HOME)/ ; )
Alternatively
#$(foreach f,$(rcFiles), [ -e $(HOME)/$f ] || ln -v -f -n -s $(PWD)/$f $(HOME)/ ; )
To not only detect files (-f) but also directories. You might want to explicitely check for files and directories [ -f ... || -d ... ].

[ -f $(HOME)/$f ]
is true only if $(HOME)/$f is (expands to) a file. The things you're getting errors on (.vim and .bash_completion.d) are directories. Try this instead:
[ -e "$(HOME)/$f" ]
(The double quotes are not strictly necessary, but will save you grief in the event that $(HOME)/$f were to expand to something with shell metacharacters in it.)

Related

Symlink dotfiles with a script

As many others have done, I want to create a repo to store my dotfile customizations. Instead of doing ln -s manually, I am using the following script to set things up.
#!/bin/bash
set -e
DIR="$HOME/Documents/Dotfiles"
OLDDIR="$HOME/Documents/Other\ Files/Dotfiles_old"
FILES=($HOME/.bash_profile)
echo "Creating $OLDDIR for backup of any existing dotfiles in ~"
mkdir -p "$OLDDIR"
echo "…done"
echo "Changing to the $DIR directory"
cd "$DIR"
echo "…done"
for FILE in "${FILES[#]}"; do
echo "Backup dotfile $FILE from ~/ to $OLDDIR"
cp -L "$HOME/$FILE" "$OLDDIR"
done
for FILE in "${FILES[#]}"; do
echo "copy $FILE from ~ to $DIR."
cp -L "$HOME/$FILE $DIR/"
echo "Creating symlink to $FILE from ~ to $DIR."
ln -sfn "$DIR/$FILE" "$HOME/$FILE";
done
shellcheck source "$HOME/.bash_profile"
When I run this, cp fails because it thinks that .bash_profile isn't there, which obviously isn't the case:
I think my path to the files may be incorrect, although shellcheck reports nothing. What am I forgetting here?
UPDATE: Made another run at this - minus the cp. The one thing I am still unsure of is the use of exit, in particular since I'm already using -e to check for errors.
Shellcheck and bash -n return 0.
#!/bin/bash
set -e
function makeFiles() {
touch .bash_profile \
touch .gitconfig \
touch .gitignore_global
}
function makeLinks() {
ln -sfn ~/Documents/Dotfiles/.bash_profile ~/.bash_profile \
ln -sfn ~/Documents/Dotfiles/.gitconfig ~/.gitconfig \
ln -sfn ~/Documents/Dotfiles/.gitignore_global ~/.gitignore_global \
source ~/.bash_profile
}
read -rp "This may overwrite existing files. Are you sure? (y/n) " -n 1;
echo "";
if [[ $REPLY =~ ^[Yy]$ ]]; then
makeFiles && makeLinks
fi;
Sigh, ln decides that .bash_profile needs to be a directory for some crazy reason.
You're building the path of the dotfile incorrectly - $FILE already contains the full path of the dotfile, and there's no need to prepend $HOME again. Try with this cp command:
cp -L "$FILE $DIR/"

OSX terminal rm -rf files from a symbolic link

Running OSX 10.11.2, I need to rm -rf the file in the location indicated in the symbolic links below for atom, npm and node as well as the links. I am currently log in as a user but terminal is in su mode.
I tried few commands for no avail. I tried to go to those locations but do not know how to.
Thank you
To start, rm itself does not have a suitable option to remove the files that the links point to. That would make it cumbersome to do this in a single command. A script helps:
#!/bin/sh
for name in "$#"
do
if [ -L "$name" ]
then
target=$(stat -f '%Y' "$name")
$0 "$target"
fi
[ -e "$name" ] && rm -rf "$name"
done
The script uses the OSX stat command to obtain the link target, and recurs to itself, to remove the target (which could be another link), and after removing the target, removes the link (or non-link, as the case may be).
In a comment, OP clarified that the link itself should not be removed. That can be done by changing the test:
#!/bin/sh
for name in "$#"
do
if [ -L "$name" ]
then
target=$(stat -f '%Y' "$name")
$0 "$target"
fi
[ -e "$name" ] && [ ! -L "$name" ] && rm -rf "$name"
done

Use Unix Executable File to Run Shell Script and MPKG File

I have 2 shell scripts and 2 mpkg installer, I am trying to use an unix excitable file to run them all. here is the script I have, but it always has error message "No such file or directory" ?
#!/bin/sh
# Find the absolute script current path
path=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
sudo sh $path/join.sh
sudo sh $path/join2.sh
#/usr/sbin/installer -dumplog -verbose -pkg $path/“esetv8.mpkg" -target /
#/usr/sbin/installer -dumplog -verbose -pkg $path/“sccm.mpkg” -target /
exit 0
Thanks so much!
The most common issue when handling variables containing paths of directories and files is the presence of special characters such as spaces. To handle those correctly, you should always quote the variables, using double quotes. Better code would therefor be:
sudo sh "$path/join.sh"
sudo sh "$path/join2.sh"
It is also advised to wrap the variables using curly braces, this can also help to avoid unwanted issues. Resulting in following code:
sudo sh "${path}/join.sh"
sudo sh "${path}/join2.sh"
While this should work, it's also appropriate to mention that it's advised to check whether the files actually exist before executing them. Checking a file for existence can be done using -f and checking execute permission using -x. The proper code is therefor:
[ -f "${path}/join.sh" ] && [ -x "${path}/join.sh" ] && sudo sh "${path}/join.sh"
[ -f "${path}/join2.sh" ] && [ -x "${path}/join2.sh" ] && sudo sh "${path}/join2.sh"
Note that if you have a bunch of these, you'd be better off executing them using a for loop. Note also that -f becomes redundant when checking -x so better code would be:
[ -x "${path}/join.sh" ] && sudo sh "${path}/join.sh"
[ -x "${path}/join2.sh" ] && sudo sh "${path}/join2.sh"

Bash to search and delete?

I need a script that will search for a file in a applications directory and delete it. If it's not there it will continue with the install.
What I'm needing deleted:
/Applications/Cydia.app/Sections/Messages(D3#TH's-Repo).png
If that's not found I want it to continue on the install. If it finds that file I want it to delete it before continuing the installation.
This is what I've got:
#!/bin/bash
file="/Applications/Cydia.app/Sections/Messages(D3#TH's-Repo).png"
if [ -f "$file" ]
then
echo "$file delteling old icon"
rm -rf /Applications/Cydia.app/Sections/Messages(D3#TH's-Repo).png
else
echo "$file old icon deleted already moving on"
fi
try this
#!/bin/bash
if [ -e <your_file> ]; then
rm -f <your_file>
fi
this should do.
Parentheses are used to start a subshell in bash, so you'll need to put your filename in double-quotes (as you did in the file test).
Change the line:
rm -rf /Applications/Cydia.app/Sections/Messages(D3#TH's-Repo).png
To:
rm -rf "${file}"
And this will remove the file (assuming no permissions problems).

Unexpected behavior from shell script's ln -sfn -v

I have the following:
if [ $kernel == 'Darwin' ]; then
$HOME="/Users/$user"
elif [ $kernel == 'Linux' ]; then
$HOME="/home/$user"
fi
# Let the script know what the dotfiles dir is
dotfiles_dir="$HOME/dotfiles"
# Making symlinks to shell files, add yours as you need
echo 'Making symlinks to shell files'
ln -sfn -v $dotfiles_dir/shells/zsh $HOME/.zsh
ln -sfn -v $dotfiles_dir/shells/zsh/zshrc $HOME/.zshrc
ln -sfn -v $dotfiles_dir/shells/bash $HOME/.bash
ln -sfn -v $dotfiles_dir/shells/bash/bash_profile $HOME/.bash_profile
ln -sfn -v $dotfiles_dir/shells/bash/bashrc $HOME/.bashrc
ln -sfn -v $dotfiles_dir/shells/profile $HOME/.profile
echo "Done at [$time]...\n"
However, this strangely outputs:
[Other output here...]
Making symlinks shell files
/Users/eduan/.zsh -> /Users/eduan/dotfiles/shells/zsh
/Users/eduan/.zshrc -> /Users/eduan/dotfiles/shells/zsh/zshrc
/Users/eduan/.bash -> /Users/eduan/dotfiles/shells/bash
./bashrc -> /Users/eduan/dotfiles/shells/bash/bashrc
/Users/eduan/.profile -> /Users/eduan/dotfiles/shells/profile
Done at [08:15]...
[Other output here...]
Can anybody tell me why I get this unexpected output? The rest of my symlinks are generated correctly, however the Bash symlinks are messed up for some reason.
BTW, this is in a big script that generates symlinks. This is only part of it, and I put the relevant parts, so that you don't get confused. :)
EDIT:
Here's the link to the latest version of the script: https://github.com/Greduan/dotfiles/blob/master/scripts/make_symlinks.sh
The darwin version of the symlink commands is missing the destination for bashrc, so going to the current directory.
I'm not sure why there are two versions of that bit of the script?
Also you only create the backup directory if it already exists, which can't be right?
This line is wrong, isn't it. Missing destination directory.
ln -sfn -v $dotfiles_dir/shells/bash/bashrc

Resources