Bash script echos but won't execute - bash

I'm creating a simple bash script to remove all Bluetooth devices from my system. What it does is use bt-device -l to list the bluetooth devices, then grabs the MAC address in between the parens, then calls bt-device -r <MACAddress> to remove the device. I'm not that great at bash scripts but when I replace the bt-device call with echo, I get the correct output. When I put the command back in it says the device wasn't found. If I manually make the call it works (outputs "Done").
Sample output of the bt-device -l command:
Added Devices:
Samico BP (12:34:56:78:9a:bc)
SensorTag 2.0 (12:34:56:78:9a:bd)
And the script I'm using:
#!/usr/bin/env bash
bt-device -l | sed 1d |
while read x; do
bt-device -r $x | cut -d "(" -f2 | cut -d ")" -f1
done
When I run it, it runs the bt-device -r command but the output is Error: Device not found as if I'd typed the MAC address wrong. If I replace the bt-device call in the script with echo, I get the list of MAC addresses as expected.
Updated script working
#!/usr/bin/env bash
bt-device -l | sed 1d |
while read x; do
bt-device -r $(echo $x | cut -d "(" -f2 | cut -d ")" -f1)
done

The problem is that you're running cut -d "(" -f2 | cut -d ")" -f1 on the output of bt-device -r, instead of on its argument.
Instead, you should write something like this:
bt-device -l | sed 1d | cut -d "(" -f2 | cut -d ")" -f1 |
while read x; do
bt-device -r $x
done

You'd want to process $x prior to using it:
bt-device -l | sed 1d |
while read x; do
dev=$( echo "$x" | cut -d "(" -f2 | cut -d ")" -f1 )
bt-device -r "$dev"
done

Related

Unable to run DSJOB command from script but the same command is running in command line

I am trying to run the command mention below to get the status of the DataStage job in a script,
JOBSTATUS = $(dsjob -jobinfo "$Project_Name" "$Job_Name" | head -l | cut -d"(" -f2 | cut -d")" -f1)
echo $JOBSTATUS
I tried using (Tilde)
JOBSTATUS = `dsjob -jobinfo "$Project_Name" "$Job_Name" | head -l | cut -d"(" -f2 | cut -d")" -f1`
echo $JOBSTATUS
But still getting the error:
JOBSTATUS: not found [no such file or directory]
At the same time if try to run this command in command line, it is running fine and giving the output.
I am new to Unix, am I missing anything?

How to output bash command to stdout and pipe to another command at the same time?

I'm working on a server and to show detailed GPU information I use these commands:
nvidia-smi
ps -up `nvidia-smi |tail -n +16 | head -n -1 | sed 's/\s\s*/ /g' | cut -d' ' -f3`
However as you can see, nvidia-smi is called twice. How can I make the output of nvidia-smi go to output and pipe to another command at the same time?
Use tee:
ps -up `nvidia-smi |tee /dev/stderr |tail -n +16 | head -n -1 | sed 's/\s\s*/ /g' | cut -d' ' -f3`
Since stdout is piped, you can't make a copy to it, so I picked stderr to show output.
If /dev/stderr is not available, use /proc/self/fd/2.

Bash command output as variable returning /bin/bash

When I run the following command in my terminal I get the expected value :
delayedjobs="$(ps aux | grep delayed_job | grep -v grep | awk '{print $11}' | awk 'END{print}' | cut -d "." -f2)" && echo $delayedjobs
However, when I run the following script, the variable returns as "/bin/bash"
#!/bin/bash
delayedjobs="$(ps aux | grep delayed_job | grep -v grep | awk '{print $11}' | awk 'END{print}' | cut -d "." -f2)"
echo ${delayedjobs}
root#central:/home/tblake# ./myscript.sh
/bin/bash
Can anyone explain this? Im having a heck of a time figuring this out.
Has you named your skript delayed_job ? Your script detect his own process.

Why does bash return the file directory when using a back tick?

I'm running this series of commands
passwd=`wc -l /etc/passwd`
echo $passwd
Returns:
34 /etc/passwd
What do I need to do to this so that it will only show the output of wc -l?
Just read from standard input instead of giving wc a file name:
$ passwd=`wc -l < /etc/passwd`
$ echo "$passwd"
86
wc still outputs quite a bit of padding, but the file name is omitted (because wc has no idea what file the data comes from).
Using awk perhaps ?
$ passwd=$(wc -l /etc/passwd | awk '{print $1}')
$ echo $passwd
32
Using cut, from cut (GNU coreutils)
$ passwd=$(wc -l /etc/passwd | cut -d" " -f1)
$ echo $passwd
32
That's the default behaviour of wc:
» wc -l /etc/passwd
28 /etc/passwd
There is no way to tell wc not to output the filename.
wc returns also the filename, but there are other ways to do it. Some examples:
passwd=`wc -l /etc/passwd | grep -o [1-9]\*`
or
passwd=`wc -l /etc/passwd | cut -f1 -d' '`
(answer from this question: get just the integer from wc in bash)

Pass the argument to if condition used in pipe

I am trying to write a script which extracts data from the file "nohup.out" using tail -f and executing dig command on condition.
#!/bin/bash
nohup proxychains firefox
tail -f nohup.out | xargs if [[ {} == *"denied"* ]]
then
dig -x `cut -d '-' -f 6 {} | cut -d ':' -f 1`&;
fi
Output of nohup.out is
|S-chain|-<>-10.1.1.16:80-<><>-93.184.220.29:80-<--denied
|S-chain|-<>-10.1.1.16:80-<><>-93.184.220.29:80-<--denied
|S-chain|-<>-10.1.1.16:80-<><>-216.58.209.77:443-<><>-OK
|S-chain|-<>-10.1.1.16:80-<><>-46.28.247.89:443-<><>-OK
With the below command I am able to extract the IP for reverse DNS lookup.
cut -d '-' -f 6 | cut -d ':' -f 1
I am not able to find a way to pass the argument to cut and if command.
What you need is to convert the if statement into an argument to bash. Doing a simplistic transform, assuming that the code in the question has a chance of working, you get:
tail -f nohup.out |
xargs -I '{}' bash -c "if [[ {} == *"denied"* ]]; then dig -x $(cut -d '-' -f 6 {} | cut -d ':' -f 1) & fi"
This is exactly the same basic treatment as was needed for a for loop being executed by nohup — you need a shell to run the built-in command. See Why can't I use Unix nohup with Bash for loop? for an exactly analogous situation.
However, on further reflection, you want to cut the string which is the IP address, not the file with that as a name, so the command needs to echo the string into the cut commands. You also have to tear your hair getting the sub-commands executed correctly; you need a backslash before the $ of $(…), or before each of the back-ticks if you insist on using `…` notation, as well as using backslash-double-quote to protect the angle-brackets in the string.
tail -f nohup.out |
xargs -I '{}' bash -c "if [[ '{}' != *denied* ]]; then echo dig -x \"\$(echo '{}' | cut -d '-' -f 6 | cut -d ':' -f 1)\" & fi"
Now we need to debate the use of the condition and two cut commands (and the general hair loss). You could use:
tail -f nohup.out |
grep -v denied |
xargs -I '{}' bash -c "echo dig -x \$(echo '{}' | cut -d '-' -f 6 | cut -d ':' -f 1) &"
or, more sensibly:
tail -f nohup.out |
awk -F '[-:]' '/denied/ { next } { print "dig -x " $7 " &" }' |
sh -x
or any of a myriad other ways to do it.
awk -F- '!/denied/ {print $6}'
splits each input line in fields separated by -, ignores the lines matching denied and extracts the 6th field of the remaining lines. With you example it outputs:
216.58.209.77:443
46.28.247.89:443

Resources