BASH Unmount multiple drives - macos

I am working on a local login script for some Macintosh clients. I would like to unmount a number of drives on the machine prior to attempting to mount them again, similar to what I do on Windows clients. Listed below is the code that I have; however, I was curious if there was a way in which to optimize this or condense the code?
if [ -d "/Volumes/Share1" ]; then
umount -f /Volumes/Share1
fi
if [ -d "/Volumes/Share2" ]; then
umount -f /Volumes/Share2
fi
if [ -d "/Volumes/Share3" ]; then
umount -f /Volumes/Share3
fi
This just seems bulky and kludgy and I am not sure how to make it any better.

Perhaps something like
VOLUMES="/Volumes/Share1 /Volumes/Share2 /Volumes/Share3"
for volume in $VOLUMES ; do
[ -d $volume ] && umount -f $volume
done
(You'd need some modifications to this to handle names with spaces in them though)

A for loop?
for dir in /Volumes/Share[123]; do
if [ -d "$dir" ] ; then
umount -f $dir
fi
done
In real life, it's unlikely to be Share[123] you want to deal with, so I'd expect you want to put the actual list there, like
for dir in "/Volumes/My Share" "/Volumes/pr0n" "/Volumes/warez"; do
etc.

You can always use functions to reduce duplication:
unmount_if_necessary() {
[ -d "$1" ] && umount -f "$1"
}
unmount_if_necessary /Volumes/Share1
unmount_if_necessary /Volumes/Share2
#...

Related

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

How can a Bash command remember and toggle a setting?

I want to have a launcher that runs a Bash commands that toggle a setting; switching the setting one way requires one command and switching it the other way requires another command. If there is no easy way to query the system to find out the status of that setting, how should Bash remember the status of the setting so that it can run the appropriate command?
An obvious solution would be to save the status as files and then check for the existence of those files to determine the appropriate command to run, but is there some neater way, perhaps one that would use volatile memory?
Here's an attempt at a toggle script using temporary files:
#!/bin/bash
main(){
settingOn="/tmp/red_on.txt"
settingOff="/tmp/red_off.txt"
if [[ ! -e "${settingOff}" ]] && [[ ! -e "${settingOn}" ]]; then
echo "no prior use detected -- creating default off"
touch "${settingOff}"
fi
if [ -f "${settingOff}" ]; then
echo "switch on"
redshift -o -t 1000:1000 -l 0.0:0.0
rm -f "${settingOff}"
touch "${settingOn}"
elif [ -f "${settingOn}" ]; then
echo "switch off"
redshift -x
rm -f "${settingOn}"
touch "${settingOff}"
fi
}
main

Delete a directory only if it exists using a shell script

I have a shell (ksh) script. I want to determine whether a certain directory is present in /tmp, and if it is present then I have to delete it. My script is:
test
#!/usr/bin/ksh
# what should I write here?
if [[ -f /tmp/dir.lock ]]; then
echo "Removing Lock"
rm -rf /tmp/dir.lock
fi
How can I proceed? I'm not getting the wanted result: the directory is not removed when I execute the script and I'm not getting Removing Lock output on my screen.
I checked manually and the lock file is present in the location.
The lock file is created with set MUTEX_LOCK "/tmp/dir.lock" by a TCL program.
In addition to -f versus -d note that [[ ]] is not POSIX, while [ ] is. Any string or path you use more than once should be in a variable to avoid typing errors, especially when you use rm -rf which deletes with extreme prejudice. The most portable solution would be
DIR=/tmp/dir.lock
if [ -d "$DIR" ]; then
printf '%s\n' "Removing Lock ($DIR)"
rm -rf "$DIR"
fi
For directory check, you should use -d:
if [[ -d /tmp/dir.lock ]]; then
echo "Removing Lock"
rm -rf /tmp/dir.lock
fi

How to use Bash to create a folder if it doesn't already exist?

#!/bin/bash
if [!-d /home/mlzboy/b2c2/shared/db]; then
mkdir -p /home/mlzboy/b2c2/shared/db;
fi;
This doesn't seem to work. Can anyone help?
First, in Bash [ is just a command, which expects string ] as a last argument, so the whitespace before the closing bracket (as well as between ! and -d which need to be two separate arguments too) is important:
if [ ! -d /home/mlzboy/b2c2/shared/db ]; then
mkdir -p /home/mlzboy/b2c2/shared/db;
fi
Second, since you are using -p switch for mkdir, this check is useless, because this is what it does in the first place. Just write:
mkdir -p /home/mlzboy/b2c2/shared/db;
and that's it.
There is actually no need to check whether it exists or not. Since you already wants to create it if it exists , just mkdir will do
mkdir -p /home/mlzboy/b2c2/shared/db
Simply do:
mkdir /path/to/your/potentially/existing/folder
mkdir will throw an error if the folder already exists. To ignore the errors write:
mkdir -p /path/to/your/potentially/existing/folder
No need to do any checking or anything like that.
For reference:
-p, --parents no error if existing, make parent directories as needed http://man7.org/linux/man-pages/man1/mkdir.1.html
You need spaces inside the [ and ] brackets:
#!/bin/bash
if [ ! -d /home/mlzboy/b2c2/shared/db ]
then
mkdir -p /home/mlzboy/b2c2/shared/db
fi
Cleaner way, exploit shortcut evaluation of shell logical operators. Right side of the operator is executed only if left side is true.
[ ! -d /home/mlzboy/b2c2/shared/db ] && mkdir -p /home/mlzboy/b2c2/shared/db
I think you should re-format your code a bit:
#!/bin/bash
if [ ! -d /home/mlzboy/b2c2/shared/db ]; then
mkdir -p /home/mlzboy/b2c2/shared/db;
fi;
Create your directory wherever
OUTPUT_DIR=whatever
if [ ! -d ${OUTPUT_DIR} ]
then
mkdir -p ${OUTPUT_DIR}
fi

pcmanfm arguements; bash

I am using ubuntu, fluxbox, pcmanfm as filemanager, xmms2 as music player.
My goal: add songs to xmms2 playlist easily with pcmanfm.
I have this script that works for single files:
path= $1
if [ -d "$path" ]; then #if directory
xmms2 radd "$path"
else
if [ -e "$path" ]; then #if not directory, but file
xmms2 add "$path"
fi
fi
I also want to have ability to add group of files
I mean select all of them and then rigth-click -> open with -> xmms2_add_script
I thougth that same code in loop should work (if pcmanfm passes just more then one argument):
args=("$#")
for path in $args; do
if [ -d "$path" ]; then
xmms2 radd "$path"
else
if [ -e "$path" ]; then
xmms2 add "$path"
fi
fi
done
but it does not work.
(I know that there is some problem running for loop through filenames with whitespaces, so tried only non-whitespaced files.)
I tried loging the output adding this
echo date >> /home/me/output.txt
echo xmms2 radd "$path" >> /home/me/output.txt
in if statements.
It seems that program is called only once when I try adding group of files.
Maybe someone knows how pcmanfm opens multiple files with some program?
(I guess other programs does it same way)
Or maybe someone just know how can I achieve my goal with a bash script?
Just in case: to add item to xmms2 playlist "xmms2 radd directory_name" or "xmms2 add file_name"
I have only basic understanding of bash so would be nice if answers wouldn't for expirienced bash programmers :)
Change your for loop to this:
for path in "${args[#]}"; do
The for loop loops over its arguments, your args variable is an array, but bash only sees the first element when you do $args.
Greg's Bash FAQ/Wiki: How can I use array variables?
This is actually how I would write that to be more readable:
for x in "$#"; do
[[ -d $x ]] && xmms2 radd "$x"
[[ -f $x ]] && xmms2 add "$x"
done

Resources