Bash piping issue - bash

I need to execute the following grep query as an argument for konsole (the kde terminal)
grep -R -i -n -A 2 -B 2 --color=always -R "searchtext" * | less -R
works for the current terminal.
konsole --workdir `pwd` -e grep -R -i -n -A 2 -B 2 --color=always -R "searchtext" * | less -R
works, but the konsole window displays the grep query without less pipe.
Ideally I want konsole to spawn as seperate process with konsole &
and send the grep command with less as an argument for konsole -e

You need to run the pipe in a shell.
konsole --workdir pwd -e bash -c 'grep -R -i -n -A 2 -B 2 --color=always -R "searchtext" * | less -R'

Related

CPU optimization for gif wallpaper

I'm using xubuntu with xfc4, for pure fun I tried to make a script which allows me to put a gif as a desktop wallpaper because this is not a default feature in xfce4.
I've already made a script which seem to work pretty fine excepted that the CPU get in a great trouble with it. So is there a way to optimize this code to do the same thing but stay friend with my CPU?
BG_GIF=/home/grasteau/Pictures/walpapper.gif
DURATION=$(exiftool -Duration walpapper.gif | sed 's/ //g' | sed 's/Duration://g' | sed 's/s//g')
PATH_IMAGE=/
mkdir -p /dev/shm/background
rm -f /dev/shm/background/*
gm convert $BG_GIF +adjoin /dev/shm/background/target%d.png
NUMBER_OF_FRAME=$(bc <<< "$(ls -1 /dev/shm/background | wc -l) - 1")
DELAY=$(bc <<< "scale=3; $DURATION/$NUMBER_OF_FRAME")
while true
do
for i in $(seq 0 $NUMBER_OF_FRAME);
do
PATH_IMAGE="/dev/shm/background/target$i.png"
xfconf-query -c xfce4-desktop -l | grep "last-image$" | while read -r line
do
xfconf-query -c xfce4-desktop -p $line -s $PATH_IMAGE
done
sleep $DELAY
done
done

Pipe grep response to a second command?

Here's the command I'm currently running:
curl 'http://test.com/?id=12345' | grep -o -P '(?<=content="2;url=).*?(?=")'
The response from this command is a URL, like this:
$ curl 'http://test.com/?id=12345' | grep -o -P '(?<=content="2;url=).*?(?=")'
http://google.com
I want to use whatever that URL is to essentially do this:
curl 'http://test.com/?id=12345' | grep -o -P '(?<=content="2;url=).*?(?=")' | curl 'http://google.com'
Is there any simple way to do this all in one line?
Use xargs with a place holder for the output from stdin with the -I{} flag as below. The -r flag is to ensure the curl command is not invoked on a empty output from previous grep output.
curl 'http://test.com/?id=12345' | grep -o -P '(?<=content="2;url=).*?(?=")' | xargs -r -I{} curl {}
A small description about the flags, -I and -r from the GNU xargs man page,
-I replace-str
Replace occurrences of replace-str in the initial-arguments with
names read from standard input.
-r, --no-run-if-empty
If the standard input does not contain any nonblanks, do not run
the command. Normally, the command is run once even if there is
no input. This option is a GNU extension
(or) if you are looking for a bash approach without other tools,
curl 'http://test.com/?id=12345' | grep -o -P '(?<=content="2;url=).*?(?=")' | while read line; do [ ! -z "$line" ] && curl "$line"; done

Generating bash script arrays with elements containing spaces from commands

I have a script that logs in to a remote host to pull a directory listing to later present options to the user. It was all working perfectly, until some of the directories started having spaces in them. I have tried several syntaxes and googled the life out of this and I am now at the end of my tether. The original command was this:
SERVERDIRS=($(sshpass -p $PASS ssh -oStrictHostKeyChecking=no $USER#$SERVER ls -l --time-style="long-iso" $FROMFOLDER | egrep '^d' | awk '{print $8}'))
I first off changed this code to be able to read the spaces like this:
SERVERDIRS=($(sshpass -p $PASS ssh -oStrictHostKeyChecking=no $USER#$SERVER ls -l --time-style="long-iso" $FROMFOLDER | egrep '^d' | cut -d' ' -f8-))
However This resulted in each word being recognised as a variable. I have tried many ways to try to solve this, two of which were:
SERVERDIRS=($(sshpass -p $PASS ssh -oStrictHostKeyChecking=no $USER#$SERVER ls -d $FROMFOLDER* |rev| cut -d'/' -f1|rev|sed s/^/\"/g|sed s/$/\"/g))
SERVERDIRS=($(sshpass -p $PASS ssh -oStrictHostKeyChecking=no $USER#$SERVER ls -d $FROMFOLDER* |rev| cut -d'/' -f1|rev|sed 's/ /\\ /g'))
SERVERDIRS=(`sshpass -p $PASS ssh -oStrictHostKeyChecking=no $USER#$SERVER ls -d $FROMFOLDER* |rev| cut -d'/' -f1|rev|sed 's/ /\\ /g'`)
How can I resolve these directories in to separate elements correctly?
If you're trying to read one array value per line instead of space-separated, then $() syntax won't help. Try readarray (Bash 4):
readarray SERVERDIRS < <(sshpass -p $PASS ssh -oStrictHostKeyChecking=no $USER#$SERVER ls -l --time-style="long-iso" $FROMFOLDER | egrep '^d' | cut -d' ' -f8-)
or assign IFS and read with -d, -r, and -a set:
IFS=$'\n' read -d '' -r -a SERVERDIRS < <(sshpass -p $PASS ssh -oStrictHostKeyChecking=no $USER#$SERVER ls -l --time-style="long-iso" $FROMFOLDER | egrep '^d' | cut -d' ' -f8-)
or, really, any other answer to this SO question.
If you're unfamiliar with <() syntax, it's known as process substitution and will allow your variable to be set in your current environment rather than the instantly-discarded subshell that a pipe would create.
Bear in mind that this process is a little dangerous; filenames can also contain newlines, so it's usually much preferred to use find ... -print0.
If you only need to list directories, try this
ls -d /usr/local/src/*/
or
ls -d /path/to/your/directory/*/
You can then loop through all directories
#!/bin/bash
aa=`ls -d /usr/local/src/*/`
for dir in "${aa}[#]"
do
echo "$dir"
done
This works if dir names contain spaces.

Piping commands in a shell script

I want to write a script that opens a shell with a few tabs, and i want each tab to execute somthing automaticly. for some reason when i pipe the commands it does not work.
gnome-terminal \
--tab-with-profile=Titleable -t "A" \
--tab-with-profile=Titleable -t "B" -e "sudo tail -f /var/log/syslog" \
--tab-with-profile=Titleable -t "C" -e "sudo tail -f /var/log/syslog | grep txt"
for some reason for Tab A&B work but in C the grep txt is ignored.
Anyone know why?
Thanks
Mat
Use a shell to call your command:
gnome-terminal \
--tab-with-profile=Titleable -t "A" \
--tab-with-profile=Titleable -t "B" -e "sudo tail -f /var/log/syslog" \
--tab-with-profile=Titleable -t "C" -e 'sh -c "sudo tail -f /var/log/syslog | grep txt"'

Run command if screen exists

I have a shell script that is supposed to kill a detached screen session if it exists. The script is
if ! screen -list | grep -q "ScreenName"; then
screen -S ScreenName -X quit
fi
Unfortunately it seems that the screen -S ... -X quit command always runs bc when I run the script and the screen session doesn't exist it still outputs "No screen sessions found." When I remove the ! and the screen session is running, it doesn't kill the running session.
What could the problem be? Thanks
To get rid of the "No screen sessions found" message, redirect the stderr of screen:
screen -list 2>/dev/null
Next, keep in mind that -X doesn't work if the session is password protected.
Then, use -r to let screen know you only want to kill detached sessions, and there's no more need for grep and if.
Putting it all together:
screen -r -S "ScreenName" -X quit 2>/dev/null
grep has a confusing convention for return codes. It returns 0 when a string is found and returns 1 when there is no match. You should omit the ! in the condition.
#Sir Athos answer is pretty good, if you don't want to ignore valid errors, or just want additional ways to do things in the future, you can use this as a reference:
screen -ls 2>&1 | grep '(Detached)' | grep -o 'ScreenName' | xargs -I{} -n 1 -r screen -r -S {} -X quit
screen -ls 2>&1 List sessions, all output to stdout
grep '(Detached)' Filter for detached sessions
grep -o 'ScreenName' Filter for ScreenName and only output ScreenName
xargs -I{} -n 1 -r screen -r -S {} -X quit Run output through xargs -n 1 one at a time, -r don't run if there is no output, -I{} use {} as the replacement location for your argument since it's not at the end, and run your command
Code Sample:
evan> screen -ls
There are screens on:
15491.pts-2.x (08/29/2013 10:43:53 AM) (Detached)
31676.pts-41.x (08/28/2013 10:55:00 AM) (Attached)
2 Sockets in /var/run/screen/S-evan.
evan> screen -ls 2>&1 | grep '(Detached)' | grep -o '15491.pts-2.x' | xargs -I{} -n 1 -r screen -r -S {} -X quit
evan> screen -ls
There is a screen on:
31676.pts-41.x (08/28/2013 10:55:00 AM) (Attached)
1 Socket in /var/run/screen/S-evan.
evan> screen -ls 2>&1 | grep '(Detached)' | grep -o '15491.pts-2.x' | xargs -I{} -n 1 -r screen -r -S {} -X quit
evan>

Resources