You are not logged in.
I'm not checking for "anything in stdout", I'm checking for a boolean. If "git pull" succeeds it returns true, if not it returns false. That's what the whole [[ $(git pull) ]] was about. The other function uses cower to check, whether the update is required. The pull command is not being called, unless the repo isn't there yet or the updater calls it, because cower said so. But yeah, I guess I could rewrite the thing with what you told me and ditch cower to check for updates.
Offline
Currently you're checking that by seeing whether anything is emitted to stdout. -_-
It is most certainly not a boolean in any way. That is command substitution: http://wiki.bash-hackers.org/syntax/expansion/cmdsubst
As an additional degree of "what?????", the test construct [[ ... ]] does not care which type of boolean you substitute (even when you're actually substituting the text "Updating bed4637..a852ab1" or possibly the text "Already up to date."), because it defaults to the test -n operator:
-n STRING
the length of STRING is nonzero
Both boolean 0 and boolean 1 have a nonzero length...
...
I assumed if you're looking at stdout instead of `if ! cmd`, then you care about that specifically; which, however, only happens when you get network fetch errors. Apparently I'm totally wrong.
Last edited by eschwartz (2018-04-12 23:40:05)
Managing AUR repos The Right Way -- aurpublish (now a standalone tool)
Offline
Apparently I'm totally wrong. :/
What I wanted to do and what I did seem to be two different things. I didn't know it defaults to -n. I tried the if statement with and without the test brackets and you are totally right!
About the git commands, to clarify what I wanted to do with pull and a test:
A 'git pull || echo "ERROR"' in a folder with a proper .git does not create an error if either the repo was up-to-date or if something was pulled. In a folder without a .git subfolder and anywhere git pull fails, it'll look like this:
$ git pull || echo "ERROR"
fatal: not a git repository (or any of the parent directories): .git
ERROR
Offline
Threw this together to make a series of demos for Pantheon 3D.
I know the way I'm getting the desktop size isn't optimal; suggestions welcome!
#!/bin/bash
##############################################################################
# This script starts a desktop recording with a desktop notificaiton caption.
#
# Caption options:
# $0 "Desktop, recording..."
# $0 title "Title, recording..."
# $0 title summary "Title, explanation"
# $0 title summary body "Title, explanation, detail"
#
# Specify FPS=number for your desired framerate (defaults to 30fps)
# Specify SIZE=LENGTHxWIDTH for your desktop size (defaults to get size from xrandr)
# Specify DELAY=seconds for your desired delay (defaults to 10s)
############################################################################## SETUP
[[ ! -d ~/Videos/Desktop/ ]] && mkdir -p ~/Videos/Desktop/ &
[[ -z ${FPS} ]] && FPS="30"
[[ -z ${SIZE} ]] && SIZE="$(xrandr | grep current | sed 's|.*current\ ||g;s|,.*||g;s|\ ||g')"
[[ -z ${DELAY} ]] && DELAY="10"
[[ -z ${DESKRECOPTS} ]] && DESKRECOPTS="-f x11grab -s ${SIZE} -r ${FPS} -i :0.0"
############################################################################## LOGIC
if [ -z "${1}" ]; then
TITLE="Desktop"
SUMMARY="recording..."
else
TITLE="${1}"
if [ -z "${2}" ]; then
SUMMARY="recording..."
else
SUMMARY="${2}"
if [ -z "${3}" ]; then
BODY=""
else
BODY="${3}"
fi
fi
fi
############################################################################## EXECUTION
sleep "${DELAY}" && notify-send -t 1500 -a "${TITLE}" "${SUMMARY}" "${BODY}" && exec ffmpeg $DESKRECOPTS ~/Videos/Desktop/"$(date +%F-%T)"-"${*}".mp4
Depends on libnotify for sending notifications, xrandr to get desktop size, and ffmpeg for recording.
Lately I've been using Dunst for displaying notifications.
Last edited by quequotion (2018-04-29 08:16:26)
makepkg-optimize · indicator-powersave · pantheon-{3d,lite} · {pantheon,higan}-qq
Offline
Well, a week ago or so I installed the google earth view extension for my chromium browser.
It is a funny little thing, which, at the opening of a new tab, puts a full-browser-size image in that tab, from google earth. The images are really nice.
Downloading that image and setting it as a background, is also nice, so this is what I did (and I kick it at every session launch, so I have a nice rotation of the backgrounds.)
As you'll see, I use xfce, but substitute it with your command for setting a backdrop. Here's the script:
# COPYRIGHT AND LEGAL STUFF ABOUT OF THE IMAGE CONTENT:
#
# Google ©2018 Cnes/Spot Image, DigitalGlobe
#earthviewbackdrop.sh
#!/bin/bash
while [ ! -f $j.jpg ]
do
j=$(((RANDOM%1198+1101)))
wget https://earthview.withgoogle.com/download/$j.jpg
done
mv $j.jpg /home/YOURHOMEHERE/Pictures/background.jpg
xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitor0/workspace0/last-image --set /home/YOURHOMEHERE/Pictures/background.jpg
#END
“The future has already arrived. It's just not evenly distributed yet.”
― William Gibson
Offline
Sometimes hard to find files on the hard drive, because I don't remember where I saved. Sometimes I remember some part of the name, or I simply want to look for any extension. This is why I wrote Ruby script "find_and_link <search_in> <link_into> <pattern>". Its mere purpose is: traverse the directory tree recursively starting from the directory "search_in", finding all files which names are matching to the given "pattern", and then makes a softlink for them in the directorty <link_into>. Sometimes files can have same name, in this case the script apply numeric prefixes for the softlink filenames in the "link_into" dir, like 0001, and so on.
#!/usr/bin/ruby
require 'find'
require 'shellwords'
require "time"
search_in=ARGV[0]
link_into=ARGV[1].chomp("/")
pattern=ARGV[2]
regex=Regexp.new(pattern,"i")
puts regex.inspect
n=0
Find.find(search_in) do |path|
#puts path if n % 100 ==0
n+=1
if FileTest.directory?(path)
if File.basename(path)[0] == '.'
Find.prune # Don't look any further into this directory.
else
next
end
else
STDOUT.puts path
STDERR.puts path
next
if File.basename(path) =~ regex then
puts path
if true then
begin
if true then
puts "-"*70
puts path
puts "-"*70
link_to="#{link_into}/#{File.basename(path)}"
prefix=""
index=0
while File.exist?(link_to)
prefix="#{"%03d" % index}_"
index+=1
link_to="#{link_into}/#{prefix}#{File.basename(path)}"
end
%x{ln -s "#{path}" "#{link_into}/#{prefix}#{File.basename(path)}" }
end
rescue => e
puts e
puts e.backtrace.inspect
end
end
end
end
end
Script contains two seemingly illogic statement "if true then" because earlier I used it to find mp3 files which duration is greater than a given value, but later I removed that code sections. Pattern isn't bash glob pattern, but Ruby compatible regex, for examle finding mp3 files, regex should be "\.mp3$"
Offline
Ah ... anselm, read `man find`
find $search_in -name $pattern -exec ln -s -t $link_into '{}' \+
Or, depending on your needs for the pattern
find $search_in -regex $pattern -exec ln -s -t $link_into '{}' \+
Plus you then have access to all the other `find` conditional tests for file size (proxy for mp3 duration) or age etc.
Last edited by Trilby (2018-05-08 02:14:33)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
Yes, much shorter, but this doesn't apply prefixes for the case of filename collisions, so that hits will be missing from the dir of the softlinks.
Last edited by anselm (2018-05-08 03:21:54)
Offline
Then add that as needed:
find $search_in -regex $pattern -exec ln --backup=numbered -s -t $link_into '{}' \+
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
This is what I am using for backups with ZFS since a 3/4 year!
https://github.com/xvzf/dataleech
It is now also in the AUR!
Offline
Here's a quick script I made to display the time since last pacman system update in conky. Hope somebody finds this useful.
#!/bin/sh
i=$(($(date +%s) - $(date -r /var/log/pacman.log +%s)))
((days=i/86400, i-=days*86400, hrs=i/3600, i-=hrs*3600, min=i/60, i-=min*60, sec=i))
printf "%dd %02dh %02dm %02ds" $days $hrs $min $sec
Offline
I was bored, on a plane, and decided to pass some time to learn about Bash arrays. This program generates a simple maze when run.
Any comments on how to improve? Bash is not my forte.
#! /bin/env bash
deltaX=(-1 0 1 0 )
deltaY=( 0 -1 0 1 )
push() {
# Remember the current location.
xStack+=($xLoc)
yStack+=($yLoc)
}
pop(){
# Get the last location we saved anf make it the current location
xLoc=${xStack["${#xStack[@]}-1"]}
yLoc=${yStack["${#yStack[@]}-1"]}
unset 'xStack[${#xStack[@]}-1]'
unset 'yStack[${#yStack[@]}-1]'
}
makeHole() {
#Turn a wall into a path at out current location
theMap[yLoc*width+xLoc]=' '
}
getDirs(){
# Find out how many directions we can go from here without creating loops.
dirs=()
for ((i=0; i<4 ; i++)); do
xTry=$(( xLoc + 2*${deltaX[i]} ))
yTry=$(( yLoc + 2*${deltaY[i]} ))
if ((xTry > 0)) && ((xTry < width)) && ((yTry > 0)) && ((yTry<height)); then
if [[ ${theMap[yTry*width+xTry]} = '#' ]]; then
dirs+=($i)
fi
fi
done
# If there are more than one direction we can choose, remember this location for later
# when we get stuck, we unwind the stack. When the stack is empty, we are done
if (( ${#dirs[@]}>1 )); then
push
fi
}
width=41
height=21
theMap=()
xStack=()
yStack=()
for ((y=0; y<height; y++)); do
for ((x=0; x<width; x++)); do
theMap[y*width+x]='#'
done
done
xLoc=1
yLoc=1
makeHole
getDirs
while (( ${#xStack[@]} > 0 )); do
if (( ${#dirs[@]}>0 )); then
dir=${dirs[(($RANDOM%${#dirs[@]}))]}
(( xLoc+=${deltaX[dir]} ))
(( yLoc+=${deltaY[dir]} ))
makeHole
(( xLoc+=${deltaX[dir]} ))
(( yLoc+=${deltaY[dir]} ))
makeHole
else
pop
fi
getDirs
done
# make an enterance and an exit
xLoc=$(( RANDOM%width/2 ))
xLoc=$(( xLoc*2+1 ))
yLoc=0
makeHole
xLoc=$(( RANDOM%width/2 ))
xLoc=$(( xLoc*2+1 ))
yLoc=$(( height-1 ))
makeHole
# Print the maze.
for ((y=0; y<height; y++)); do
printf "\n"
for ((x=0; x<width; x++)); do
printf "%s" "${theMap[y*width+x]}"
printf "%s" "${theMap[y*width+x]}"
done
printf "\n"
for ((x=0; x<width; x++)); do
printf "%s" "${theMap[y*width+x]}"
printf "%s" "${theMap[y*width+x]}"
done
done
printf "\n"
Nothing is too wonderful to be true, if it be consistent with the laws of nature -- Michael Faraday
Sometimes it is the people no one can imagine anything of who do the things no one can imagine. -- Alan Turing
---
How to Ask Questions the Smart Way
Offline
Hi
I like trying out new and cool things from "the linux world" so I end up installing lots of packages and never remember to delete them. I don't really know why I care about that but it kinda feels wrong to have so much stuff installed.
So I read a bit of the AWK book (strongly recommended) and made this thing:
#!/usr/bin/gawk -f
BEGIN {
# make array of regexes for recognizing package managers
Managers[1] = "sudo pacman"
Managers[2] = "(sudo )?yay"
Managers[3] = "(sudo )?pacaur"
}
function IsInstalling(histLine) {
for (i = 1; i <= length(Managers); i++) {
if (histLine ~ Managers[i] " -S[yu]* ") {
return 1 # True
}
}
return 0 # False
}
function IsGrouped(histLine) {
return histLine ~ "# *[-_a-zA-Z0-9]+ *$"
}
function IsUninstalling(histLine) {
for (i = 1; i <= length(Managers); i++) {
if (histLine ~ Managers[i] " -R") {
return 1 # True
}
}
return 0 # False
}
# can't return array, so it must be passed as a parameter then filled
function PackageNames(histLine, result) {
# empty the result array to avoid problems
for (i in result) {
delete result[i]
}
b = 0
for (i = 2; i <= NF; i++) {
if (b && $i !~ "^[-#]") {
result[$i] = "You should not see this"
} else if (!b && $i ~ "^-") {
b = 1
} else if ($i ~ "^#") {
return
}
}
}
IsInstalling($0) && IsGrouped($0) {
PackageNames($0, result)
for (package in result) {
Groups[$NF][package] = "You shouldn't see this either"
}
}
IsUninstalling($0) {
PackageNames($0, result)
for (group in Groups) {
for (uninstalled in result) {
if (uninstalled in Groups[group]) {
delete Groups[group][uninstalled]
}
}
}
}
END {
for (group in Groups) {
print "group name: " group
for (package in Groups[group]) {
print package
}
print ""
}
}
Usage examples: whenever I want to install some things and remember to uninstall them if I want to,
yay install mpd ncmpcpp mpc # mpd
yay install rustc rust-racer # rust-dev
Then, to clean my system, a
history | awk -f thisfile
tells me what groups of packages I have made and what packages they have.
There are probably lots of improvements to be made, but I'm not much of an AWK wizard. (And I think the better choice would have been Perl anyway).
Offline
vicentereyes, the biggest issue would be that 'history' is limited both in having a finite length and in having a scope of the current shell. But every package installed is logged in pacman's log which would be a far better target and would need very little processing by awk/perl/etc. For example, I think the following starting point would have about the same result:
sed -n 's/.*pacman -S[^ ]* \([a-zA-Z0-9].*\).$/\1/p' /var/log/pacman.log
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
Trilby, the purpose of this seems to be to grab the bash comment describing the installation reason, which won't be in the pacman log.
Managing AUR repos The Right Way -- aurpublish (now a standalone tool)
Offline
Ah, sorry, I missed that.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
Video to GIF via ffmpeg:
[[ -f "${1}" ]] && \
ffmpeg -y -t 3 -i "${1}" -vf fps=10,scale=320:-1:flags=lanczos,palettegen "${1}"-palette.png && \
exec ffmpeg -t 3 -i "${1}" -i "${1}"-palette.png -filter_complex "fps=10,scale=320:-1:flags=lanczos[x];[x][1:v]paletteuse" "${1}".gif
makepkg-optimize · indicator-powersave · pantheon-{3d,lite} · {pantheon,higan}-qq
Offline
#! /usr/bin/bash
#Color chart to compare foreground/background colors in
#terminal. Terminal needs to be at least 80 char wide.
FG=(' black ' ' red ' ' green ' ' yellow' ' blue '
'magenta' ' cyan ' ' white ')
BG=('Def' 'Blk' 'Red' 'Grn' 'Yel' 'Blu' 'Mag' 'Cya' 'Wht')
str=$(printf "%74s")
echo " ┌"${str// /─}"┐"
for b in {0..8}; do
bg=$((b+39))
echo -en "\033[0m ${BG[b]} │ "
for f in {0..7}; do
echo -en "\033[${bg}m\033[$((f+30))m ${FG[f]} "
done
echo -en "\033[0m │\n\033[0m │ "
for f in {0..7}; do
echo -en "\033[${bg}m\033[1;$((f+30))m ${FG[f]} "
done
echo -en "\033[0m │\n\033[0m"
echo " ├"${str// /─}"┤"
done
echo " └"${str// /─}"┘"
#https://en.wikipedia.org/wiki/Box-drawing_character
#Look at pacman -Ss gucharmap , copy/paste
Offline
Print recently added albums when I mount my portable music drive:
#!/usr/bin/env bash
# find recently added tunes
musicdir="/media/Apollo/Music"
if [[ -d "$musicdir" ]]; then
IFS=$'\n'
tunes=($(find Music -maxdepth 2 -type d -mtime -20 -printf "%p\n"))
if (( ${#tunes[@]} > 1 )); then
for i in "${tunes[@]}"; do
printf "${i#*\/}" | awk '/\57/ {gsub(/\57/, " - ");printf "• %s\n", $0}'
done
else
printf " • %s\n" "No updated music…"
exit 0
fi
else
printf "%s\n" "Apollo not mounted…"
exit 1
fi
# vim:set ts=2 sts=2 sw=2 et:
Offline
Why loop through entries just to individually trim each one then pass each one to it's own awk invocation? You can just pass all the output through a single instance of awk (or sed).
Also, some may argue this is a stylistic point, but the merits to me seem overwhelming to refactor conditional blocks like that to invert the logic and move most of the content out of a conditional branch, e.g.:
if [[ ! -d $musicdir ]]; then
echo 'Apollo not mounted...'
exit 1
fi
# go on here with the real work with one less level of nesting/indentation
In fact, if you don't need verbosity, but can use just a non-zero exit as sign of an error and a zero exit with no output as a sign of no new music, this could just be a couple lines:
#!/bin/bash
musicdir="/media/Apollo/Music"
[[ -d "$musicdir" ]] || exit 1
find $musicdir -maxdepth 2 -type d -mtime -20 -printf "%f\n" | sed 's/\\57/ - /g; s/^/• /'
And once there, it should be clear that find itself will be kind enough to provide a non-zero exit if we gave it a non-existent path:
musicdir="/media/Apollo/Music"
find $musicdir -maxdepth 2 -type d -mtime -20 -printf "%f\n" | sed 's/\\57/ - /g; s/^/• /'
And of course at that point there's arguably no need to even have a variable for musicdir and it becomes a one-liner ... or even an alias.
And if I switch back to awk from sed, it's actually pretty easy to do with POSIX tools too (POSIX find doesn't have printf):
find /media/Apollo/Music -maxdepth 2 -type d -mtime 20 | awk -F/ '{gsub(/\57/, " - "); printf "• %s\n", $5; }'
Though I'm guessing a bit on the '$5' there, it may be a different column depending on exactly how your directory tree looks and what you want as output. Also, I'd substitute gsub with sub unless there really are multiple occurrences on each line.
Last edited by Trilby (2018-07-22 02:02:45)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
Most of it is a result of not thinking like a programmer: having a cascading series of conditions is just how I frame it.
I do like more verbosity: it provides context when something behaves unexpectedly: like knowing that I forgot to plug the drive in or it has been some time since I added new albums.
Why loop through entries just to individually trim each one then pass each one to it's own awk invocation?
That's a good point. It was just my roundabout way of pretty printing. Your suggestion is more efficient, and more elegant. Thanks!
Offline
I wanted the ability to stabilize videos without needing to rely on the reddit "stabbot" bot. So I copied the commands from the bot into a Bash script.
stabbot source code: https://gitlab.com/juergens/stabbot
#!/usr/bin/bash
# See https://gitlab.com/juergens/stabbot/blob/master/stabVid.py
# Zoom
ffmpeg -y -i "$1" -vf scale="trunc((iw*1.15)/2)*2:trunc(ow/a/2)*2" -pix_fmt yuv420p zoomed.mp4
# Calculate stabilization
ffmpeg -y -i zoomed.mp4 -vf vidstabdetect -f null -
# Stabilize!
ffmpeg -y -i zoomed.mp4 -vf vidstabtransform=smoothing=20:crop=black:zoom=-15:optzoom=0,unsharp=5:5:0.8:3:3:0.4 "${1%.*}"-stab.mp4
# Remove temporary files
rm -f transforms.trf zoomed.mp4
Save as "stab", and just run it with the video you want stabilize: "stab video.mp4"
Last edited by drcouzelis (2018-08-06 12:33:08)
Offline
Recently found out that aarchup (desktop pacman and AUR updates notifier) wasn't honouring the IgnorePkg directive from /etc/pacman.conf for AUR packages. In the end I created my own Bash script, upnote.sh, similar to aarchup but with some improvements. Please take note of the dependencies, edit the configuration in the start of the script to your preferences, and add to your Startup Applications (script to be run as the desktop user).
#!/bin/bash
#
# upnote.sh
#
# dependencies: - checkupdates (included in pacman-contrib)
# - auracle (AUR auracle-git)
# - notify-send.sh (AUR notify-send.sh)
# configuration
HEADER='New updates for Arch Linux available:'
ICON='/usr/share/icons/Adwaita/48x48/apps/system-software-install.png'
MAX=30 # maximum number of items to show
SHOW=600 # show notification for * seconds, 0 will show notification until the next updates check
WAIT=3600 # check for updates every * seconds (value should be greater than SHOW value)
# functions
containsElement () {
local e match="$1"
shift
for e; do [[ "$e" == "$match" ]] && return 1; done
return 0
}
# main
while true; do
#PACMAN
#checkupdate honours IgnorePkg, so no need to filter ourselves
readarray -t PACARRAY < <(checkupdates 2> /dev/null)
COUNT=0
FIRST=true
for PAC in "${PACARRAY[@]}"; do
if [ $FIRST = true ]; then
STR="Pacman updates:"
FIRST=false
fi
if [ $COUNT -lt $MAX ]; then
STR+="\n - $PAC"
((COUNT++))
else
break
fi
done
#AUR
#auracle does not honour IgnorePkg, so we need to filter these out ourselves
readarray -t AURARRAY < <(auracle sync 2> /dev/null)
readarray -t IGNOREARRAY < <(pacman-conf IgnorePkg)
FIRST=true
for AUR in "${AURARRAY[@]}"; do
containsElement $(echo "$AUR" | awk '{print $1;}') "${IGNOREARRAY[@]}"
if [ $? -eq 0 ]; then
if [ $COUNT -lt $MAX ]; then
if [ $FIRST = true ]; then
if [ "$STR" ]; then
STR+="\n\nAUR updates:"
else
STR="AUR updates:"
fi
FIRST=false
fi
STR+="\n - $(echo "$AUR" | awk '{print $0;}')"
((COUNT++))
else
break
fi
fi
done
#notify
IFS=""
if [ "$STR" ]; then notify-send.sh -R /var/tmp/upnote -u critical -i $ICON $HEADER $STR; fi
#close notification
if [ $SHOW -gt 0 ]; then
sleep $SHOW
if [ "$STR" ]; then notify-send.sh -s $(< /var/tmp/upnote); fi
fi
#wait for next run
sleep $((WAIT - SHOW)) 2> /dev/null
#reset variables and arrays for the next run
AURARRAY=()
IGNOREARRAY=()
PACARRAY=()
STR=""
done
# end
exit 0
Last edited by Crouze (2018-10-06 16:13:45)
Offline
Please don't sed pacman.conf yourself, we've recently added a special program called pacman-conf which is provided in the pacman package itself, specifically to safely parse pacman.conf using the actual supported pacman.conf rules (like "Include").
pacman-conf IgnorePkg
Managing AUR repos The Right Way -- aurpublish (now a standalone tool)
Offline
Eschwartz, to be fair, they didn't sed pacman.conf themselves. They read pacman.conf line by line in a clumsy and pointless loop and sed''ed part of each line for no reason only to check whether it matched 'IgnorePkg' and then only to oddly and conditionally append a space then a value to a simple variable when an array would be much easier needing no conditional or spaces.
Of course the entire loop could have been replaced by a single clean efficient sed command. And that in turn is what would be a candidate to be replaced by pacman-conf.
If pacman-conf were not an option, that entire loop could just be:
IGNORE=$(sed -n 's/^IgnorePkg[^=]*=//p' /etc/pacman.conf)
# or better as an array
IGNORE=($(sed -n 's/^IgnorePkg[^=]*=//p' /etc/pacman.conf))
Last edited by Trilby (2018-10-03 13:49:10)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline