How can I determine the volume name of CD/DVD in bash? - macos

I'm trying to figure out how to get a bash script to automatically determine the path to a CD/DVD in order to process it. Running a Mac (10.7.4) the disk shows up at:
/Volumes/[Volume_name]
Since the volume name changes depending on the disk, I'm having to input that part manually. The operating system obviously knows it's a CD/DVD because of the way the controls work. Is it possible for bash to use whatever the OS uses to determine there is a CD/DVD and provide the path to it?

I use drutil.
drutil uses the DiscRecording framework to interact with attached burning devices.
#!/bin/bash
id=$(drutil status |grep -m1 -o '/dev/disk[0-9]*')
if [ -z "$id" ]; then
echo "No Media Inserted"
else
df | grep "$id" |grep -o /Volumes.*
fi

Given a UNIX block device name, diskutil info's output is easier to parse than mount's. For instance, this
function get_disk_mountpoint () {
diskutil info $1 | perl -ne 'print "$1\n" if /^ Mount Point: +(.*)/';
}
works. Trouble is, OS X also dynamically assigns /dev/disk? devices to removable media, so you still need something like
function get_optical_mountpoints () {
for i in $(diskutil list | egrep ^/); do
if diskutil info $i | egrep -q '^ Optical Drive Type:' ; then
get_disk_mountpoint $i
fi
done
}
to list the mount points for optical drives specifically.

If a disc is mounted you can use mount to view where it's mounted.

Putting together the pieces from above, I think this will do what you want:
get_cd_volume() {
local rc=1
for disk in $(diskutil list | grep ^/); do
if diskutil info "$disk" | grep -q Optical; then
df | sed -ne "s,^$disk.*\(/Volumes.*\)$,\1,p"
rc=0
fi
done
if (( rc )); then
echo >&2 "No volume mounted."
fi
return $rc
}

Related

How to change between speakers and USB headset using a script on Ubuntu?

I am trying to write a script to change between speakers and headset. I want to be able to change the output and the input with a shortcut.
I used these commands to see my audio devices :
$ pacmd list-sinks | grep alsa_output
name: <alsa_output.usb-Logitech_Logitech_USB_Headset-00.analog-stereo>
name: <alsa_output.pci-0000_00_1b.0.analog-stereo>
$ pacmd list-sources | grep alsa_input
name: <alsa_input.usb-Logitech_Logitech_USB_Headset-00.analog-mono>
name: <alsa_input.usb-093a_262c-01.analog-mono>
name: <alsa_input.pci-0000_00_1b.0.analog-stereo>
And wrote this script so I can change the default audio device.
#! /bin/bash
pacmd set-default-sink alsa_output.usb-Logitech_Logitech_USB_Headset-00.analog-stereo
pacmd set-default-source alsa_input.usb-Logitech_Logitech_USB_Headset-00.analog-mono
exit 0
When I run this with the command
sudo ./usb-speakers.sh
I get this messages :
No PulseAudio daemon running, or not running as session daemon.
Home directory not accessible: Permission denied
No PulseAudio daemon running, or not running as session daemon.
I found several questions with similar problems but I can't make anything work for me.
https://github.com/mk-fg/pulseaudio-mixer-cli/blob/master/README.md says:
Kinda like alsamixer, focused not on sink volume levels (which can actually be controlled via alsamixer, with alsa-pulse plugin), but rather on volume of individual streams, so you can turn down the music to hear the stuff from games, mumble, skype or browser.
In addition to interactive UI, script allows to match and configure sink/stream parameters via config file, so that when specific sink or stream appears, e.g. its volume can be capped, port changed, UI title adjusted, be hidden in UI, stuff like that.
I found this script (I can't remember where ) which solve all my problems
#!/bin/bash
declare -i sinks=(`pacmd list-sinks | sed -n -e 's/\**[[:space:]]index:[[:space:]]\([[:digit:]]\)/\1/p'`)
declare -i sinks_count=${#sinks[*]}
declare -i active_sink_index=`pacmd list-sinks | sed -n -e 's/\*[[:space:]]index:[[:space:]]\([[:digit:]]\)/\1/p'`
declare -i next_sink_index=${sinks[0]}
#find the next sink (not always the next index number)
declare -i ord=0
while [ $ord -lt $sinks_count ];
do
echo ${sinks[$ord]}
if [ ${sinks[$ord]} -gt $active_sink_index ] ; then
next_sink_index=${sinks[$ord]}
break
fi
let ord++
done
#change the default sink
pacmd "set-default-sink ${next_sink_index}"
#move all inputs to the new sink
for app in $(pacmd list-sink-inputs | sed -n -e 's/index:[[:space:]]\([[:digit:]]\)/\1/p');
do
pacmd "move-sink-input $app $next_sink_index"
done
#display notification
declare -i ndx=0
pacmd list-sinks | sed -n -e 's/device.description[[:space:]]=[[:space:]]"\(.*\)"/\1/p' | while read line;
do
if [ $(( $ord % $sinks_count )) -eq $ndx ] ; then
notify-send -i notification-audio-volume-high --hint=string:x-canonical-private-synchronous: "Sound output switched to" "$line"
exit
fi
let ndx++
done;
just copy and paste it in an empty document and save it as
audio-device-swithcer.sh
then save it to your usr/local/bin directory
If you want to add a shortcut go to Keyboard & Shortcuts and add a new shortcut.
As a command just put your audio-device-switcher.sh file
That's all guys that worked perfectly for me .
And thank you for your answers.

Check if two files are on the same volume in bash

Is there a way to check if two files are on the same volume in bash on Mac OS X?
Or, equivalently, to check if a given file is on the boot volume?
I've tried using ln and checking to see if it fails, but sometimes ln fails for reasons other than the cross-device link error.
I also tried using a function that prints the path of a file and then checking to see if that path contains /Volumes/ as a prefix, but not all of my remote volumes get mounted to /Volumes/.
Is there another way?
You are asking if two files are on the same filesystem. The canonical way of checking this is to call the stat() system call on the two files and check if they have the same st_dev value, where st_dev identifies the device on which the file resides.
You can use the stat command in bash to perform this test:
device=$(stat -f '%d' /path/to/file)
So, to check if two files are on the same filesystem:
dev1=$(stat -f '%d' /path/to/file1)
dev2=$(stat -f '%d' /path/to/file2)
if [ "$dev1" = "$dev2" ]; then
echo "file1 and file2 are on the same filesystem"
fi
The above works under OS X; the same check can be performed on Linux, but the stat command requires -c or --format instead of -f.
With df:
f1="$(df -P /path/to/file1.txt | awk 'NR!=1 {print $1}')"
f2="$(df -P /path/to/file2.txt | awk 'NR!=1 {print $1}')"
if [[ "$f1" = "$f2" ]]; then
echo "same filesystem"
else
echo "different filesystem"
fi

Bash: How to enforce output to one line?

I wrote the following Nagios check, which checks /etc/fstab for mounts and by using df checks if they are mounted properly:
#!/bin/bash
# Check mounts based on /etc/fstab
grep="/bin/grep"
awk="/bin/awk"
df="/bin/df"
mounts=$($grep nfs /etc/fstab | $awk '{print $2}')
# Check if mounts exist
for mount in $mounts; do
$df | $grep $mount &>/dev/null
if [ "$?" -eq "0" ]; then
msg="Mount $mount is mounted!"
else
msg="Mount $mount is not mounted!"
fi
echo $msg
done
When I run the check it returns a proper result:
[root#nyproxy5 ~]# ./check_mount.sh
Mount /proxy_logs is mounted!
Mount /proxy_dump is mounted!
Mount /sync_logs is mounted!
[root#nyproxy5 ~]#
But I want the output of the script to be 1 line rather than 3 lines, how can it be achieved?
I realize that the way the script is written at the moment doesn't allow it, even the "Mount X is mounted" message should be changed, but I'm having a hard time with the logic.
Thanks in advance
Change echo $msg to echo -n $msg
-n option will avoid printing newline
There is a general solution in case of some complicated command. Newlines or any other character could be removed this way:
./script.sh | tr -d '\n'
Or a win32 executable in cygwin:
./asd.exe | tr -d '\r\n'

How to check if filepath is mounted in OS X using bash?

How do I perform the mount only if it has not already been mounted?
This is on OS X 10.9 and this is what I have currently:
#!/bin/bash
# Local mount point
LOCALMOUNTPOINT="/folder/share"
# Perform the mount if it does not already exist
if ...
then
/sbin/mount -t smbfs //user:password#serveraddress/share $LOCALMOUNTPOINT
else
echo "Already mounted"
fi
While #hd1's answer gives you whether the file exists, it does not necessary mean that the directory is mounted or not. It is possible that the file happen to exist if you use this script for different machines or use different mount points. I would suggest this
LOCALMOUNTPOINT="/folder/share"
if mount | grep "on $LOCALMOUNTPOINT" > /dev/null; then
echo "mounted"
else
echo "not mounted"
fi
Note that I include "on" in grep statement based on what mount command outputs in my machine. You said you use MacOS so it should work, but depending on what mount command outputs, you may need to modify the code above.
This is what I use in my shell scripts on OS X 10.7.5
df | awk '{print $6}' | grep -Ex "/Volumes/myvolume"
For OS X 10.10 Yosemite I have to change to:
df | awk '{print $9}' | grep -Ex "/Volumes/myvolume"
For me from this solution in stackoverflow_QA_Check if a directory exists in a shell script
[ -d /Volumes/ ] && echo "Already mounted /Volumes/ in OS X" || echo "Not mounted"
to use that
# 2 lines
$LOCALMOUNTPOINT="/folder/share" ;
[ -d $LOCALMOUNTPOINT ] && echo "Already mounted $LOCALMOUNTPOINT in OS X" || /sbin/mount -t smbfs //user:password#serveraddress/share $LOCALMOUNTPOINT
Here is Stackoverflow_QA_how-can-i-mount-an-smb-share-from-the-command-line
additional link about smb which I don't know well
# Here is my solution
$LOCALMOUNTPOINT="/folder/share" ;
[ ! -d $LOCALMOUNTPOINT ] && mkdir $LOCALMOUNTPOINT && /sbin/mount -t smbfs //user:password#serveraddress/share $LOCALMOUNTPOINT || echo already mounted $LOCALMOUNTPOINT
I have to make new folder for my SMOOTH use before mounting that.
so I added mkdir $LOCALMOUNTPOINT
Thank you I learned a lot with this case.
Have A nice day!!! ;)

Shell script help

I need help with two scripts I'm trying to make as one. There are two different ways to detect if there are issues with a bad NFS mount. One is if there is an issue, doing a df will hang and the other is the df works but there is are other issues with the mount which a find (mount name) -type -d will catch.
I'm trying to combine the scripts to catch both issues to where it runs the find type -d and if there is an issue, return an error. If the second NFS issue occurs and the find hangs, kill the find command after 2 seconds; run the second part of the script and if the NFS issue is occurring, then return an error. If neither type of NFS issue is occurring then return an OK.
MOUNTS="egrep -v '(^#)' /etc/fstab | grep nfs | awk '{print $2}'"
MOUNT_EXCLUDE=()
if [[ -z "${NFSdir}" ]] ; then
echo "Please define a mount point to be checked"
exit 3
fi
if [[ ! -d "${NFSdir}" ]] ; then
echo "NFS CRITICAL: mount point ${NFSdir} status: stale"
exit 2
fi
cat > "/tmp/.nfs" << EOF
#!/bin/sh
cd \$1 || { exit 2; }
exit 0;
EOF
chmod +x /tmp/.nfs
for i in ${NFSdir}; do
CHECK="ps -ef | grep "/tmp/.nfs $i" | grep -v grep | wc -l"
if [ $CHECK -gt 0 ]; then
echo "NFS CRITICAL : Stale NFS mount point $i"
exit $STATE_CRITICAL;
else
echo "NFS OK : NFS mount point $i status: healthy"
exit $STATE_OK;
fi
done
The MOUNTS and MOUNT_EXCLUDE lines are immaterial to this script as shown.
You've not clearly identified where ${NFSdir} is being set.
The first part of the script assumes ${NFSdir} contains a single directory value; the second part (the loop) assumes it may contain several values. Maybe this doesn't matter since the loop unconditionally exits the script on the first iteration, but it isn't the clear, clean way to write it.
You create the script /tmp/.nfs but:
You don't execute it.
You don't delete it.
You don't allow for multiple concurrent executions of this script by making a per-process file name (such as /tmp/.nfs.$$).
It is not clear why you hide the script in the /tmp directory with the . prefix to the name. It probably isn't a good idea.
Use:
tmpcmd=${TMPDIR:-/tmp}/nfs.$$
trap "rm -f $tmpcmd; exit 1" 0 1 2 3 13 15
...rest of script - modified to use the generated script...
rm -f $tmpcmd
trap 0
This gives you the maximum chance of cleaning up the temporary script.
There is no df left in the script, whereas the question implies there should be one. You should also look into the timeout command (though commands hung because NFS is not responding are generally very difficult to kill).

Resources