You are not logged in.
... and get Trilby a cardiac arrest
No worries. Scripts that involved to do something so trivial don't even get read, though my thoughts on the whole thing can be summed up by the license name with a little formating:
while true; DO
WHAT THE FUCK?
done
read -p "YOU WANT TO PUBLIC LICENSE?" response
Once you break out of the loop, you'll want to respond "no" at the prompt
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
Until I find some satisfying solution for the lack of Google sync stuff in Chromium, I have installed google-chrome from the AUR. The maintainers seem to be rather quick, but I don't want to bet on that. The Idea: If extra/chromium is newer than google-chrome on the AUR, then I want to know that.
It requires expac and either auracle or jq. It comes with a rudimentary hook.
chromcheck:
#!/bin/bash
if ! pacman -Qq google-chrome 2>/dev/null 1>/dev/null; then
echo "NOTE: google-chrome not installed. Nothing to do."
exit 0 # not having google-chrome is fine
fi
if pacman -Qq expac 2>/dev/null 1>/dev/null; then
chrome_query="$(expac -Q %v google-chrome | sed "s/-[0-9]*//")"
chromium_sync="$(expac -S %v chromium | sed "s/-[0-9]*//")"
else
echo "ERROR: expac is required"
exit 1
fi
if pacman -Qq auracle-git 2>/dev/null 1>/dev/null; then
chrome_aur="$(auracle info google-chrome | grep Version | sed "s/.* : //" | sed "s/-[0-9].*//")"
elif pacman -Qq curl jq 2>/dev/null 1>/dev/null; then
chrome_aur="$(curl -s 'https://aur.archlinux.org/rpc.php/?v=5&type=info&arg[]=google-chrome' | jq -r .results[].Version | sed "s/-[0-9]*//")"
else
echo "ERROR: Either auracle or both curl and jq must be installed."
exit
fi
if [[ ! "$chrome_query" == "$chromium_sync" ]]; then
echo "local/Chrome: $chrome_query"
echo "extra/Chromium: $chromium_sync"
echo "aur/Chrome: $chrome_aur"
fi
chromcheck.hook
[Trigger]
Operation = Upgrade
Type = Package
Target = *
[Action]
Description = compare local/google-chrome with extra/chromium and inform about the AUR version
When = PostTransaction
Exec = /usr/local/bin/chromcheck
Any comments besides "learn awk to avoid grep|sed|sed"?
EDIT: The hook works! My first hook.
EDIT: Found a typo. It's fine in the script, wonder what happened during copy-paste.
EDIT: Ok, let's see how many errors I can find myself. Why was this even working?
EDIT: Hopefully the final version. It now checks for auracle and if that's not there, it falls back to curl + jq.
Last edited by Awebb (2021-04-16 16:33:54)
Offline
I use a terminal far more often than any menus, and use this 'W' script pretty often.
W = find files in $PATH given part of the name, w/optional grep. ('W' is from 'which'...)
$ cat bin/W
#!/bin/bash
# Find files in $PATH matching *$1* [| grep -i $2]
#
if [ $# -lt 1 ]
then
echo Usage: `basename $0` pattern [ pattern2 ]
exit 1
fi
if [ $# -eq 1 ]; then
echo $PATH | sed 's/^/ls -A /' | sed 's/:/ |grep -i '$1'; ls -A /g' | sed 's/$/ |grep -i '$1'/' | bash | sort
exit 0
fi
if [ $# -eq 2 ]; then
echo $PATH | sed 's/^/ls -A /' | sed 's/:/ |grep -i '$1'; ls -A /g' | sed 's/$/ |grep -i '$1'/' | bash | sort | grep -i $2
exit 0
fi
$ W player
Flashplayer
cdda-player
mplayer
smplayer
$
$ W player m
mplayer
smplayer
"If you do not change direction, you may end up where you are heading." -- L.T.
Offline
Any comments besides "learn awk to avoid grep|sed|sed"?
Well ... learn sed to avoid grep|sed|sed
... | sed -n '/Version/{s/.* : //;s/-[0-9].*//;p}'
But the pipelines in Flemur's "W" are a bit more ... in need a single regex search can just be this:
IFS=:; find $PATH -iname "*$1*" -exec basename '{}' \;
Multiple:
IFS=:; find $PATH -iname "*$1*" -iname "*$2*" -exec basename '{}' \;
No pipelines needed at all, and certainly no need to parse `ls` output. In fact, the whole thing should be able to be just this:
#!/bin/sh
IFS=:; eval find $PATH $(printf ' -iname "*%s*"' $@) -exec basename "'{}' \;"
Last edited by Trilby (2021-04-16 13:32:36)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
In fact, the whole thing should be able to be just this:
#!/bin/sh IFS=:; eval find $PATH $(printf ' -iname "*%s*"' $@) -exec basename "'{}' \;"
Cool! I don't understand it, but I no longer understood mine either, not long after making it.
"If you do not change direction, you may end up where you are heading." -- L.T.
Offline
Awebb wrote:Any comments besides "learn awk to avoid grep|sed|sed"?
Well ... learn sed to avoid grep|sed|sed
... | sed -n '/Version/{s/.* : //;s/-[0-9].*//;p}'
That seems to be my recurring theme :-D
Offline
Cool! I don't understand it, but I no longer understood mine either, not long after making it.
The combined version with the 'eval' is admittedly a bit awkward. What's the line about 'eval' being a misspelling of 'evil'? But it's the cleanest way I thought of to include any number (greater than zero) of patterns to match. Hopefully the separate versions for one or two patterns would be understandable:
IFS=:
This is just so we can pass $PATH to find as the location(s) to search (IFS is the Input Field Separator variable, and $PATH includes paths separated by a ':'). I think you could instead do something like this for similar effect:
find $(echo $PATH | tr ':' ' ') ...
Then we use the "-iname" flag for find so it matches file names case insensitively against "*$1*", the asterisks so that $1 can appear anywhere in the filename and still match. Then it ends with find's "-exec" flag which runs a certain command on each result. Here we use 'basename' on each result to get the ... basename. You can see the result without this is still valid, just not as pretty:
IFS=:; find $PATH -iname "*$1*"
This will produce the same results, but each one will include the full path.
In reality, you may want to include another flag to find like "-executable" to limit results to files that are executable. I'm not sure if there should be any nonexecutable content in $PATH locations, but it's certainly possible, and you wouldn't want those files listed.
Last edited by Trilby (2021-04-16 15:34:49)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
I've fixed my script. Still a lot of piping, but that'll be homework for another day.
Offline
IFS=:; find $PATH -iname "*$1*"
This will produce the same results, but each one will include the full path.
Hey, thanks!, that's what I usually prefer (sometimes the same name is in more than one place, etc) so I changed my W to
#!/bin/sh
# from Trilby, Arch forums
# IFS=:; find $PATH -iname "*$1*" -iname "*$2*" -exec basename '{}' \;
IFS=:
eval find $PATH $(printf ' -iname "*%s*"' $@)
As a side benefit it now works with a bunch of arguments (Edit: with no args it lists all the files in $PATH):
$ W la p r m y
/usr/bin/mplayer
/usr/bin/smplayer
Last edited by Flemur (2021-04-16 16:54:56)
"If you do not change direction, you may end up where you are heading." -- L.T.
Offline
@Flemur: This reminds me a bit of dmenu_run from the dmenu package.
Offline
I wrote myself an emergency reboot program that can be used to forcibly reboot a system using Sysrq if the internal disk produces I/O errors due to file system issues and the system cannot be rebooted otherwise [1]:
Needless to say, that you should not use this for a reboot during normal operations, since it will result in data loss.
I use it with the suid bit set (since all users on the target systems are trusted) and added it to the initramfs BINARIES=().
er.c
/**
er.c - Emergency reboot: Reboot a Linux system using sysrq.
(C) 2021 Richard Neumann <mail at richard dash neumann period de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this library. If not, see <http://www.gnu.org/licenses/>.
Note:
The compiled binary must have the suid bit set
in order to work for an arbitrary user.
*/
#include <errno.h>
#include <stdio.h>
int write_to_file(char* filename, char* value)
{
int rc;
FILE *fp;
fp = fopen(filename, "w");
if (fp == NULL)
return -EIO;
rc = fprintf(fp, value);
fclose(fp);
return rc;
}
int main()
{
int rc;
rc = write_to_file("/proc/sys/kernel/sysrq", "1");
if (rc > 0)
rc = write_to_file("/proc/sysrq-trigger", "b");
if (rc > 0)
return 0;
return rc;
}
[1] Current scenario that triggered the development:
$ ssh 1120.terminals.homeinfo.intra /bin/sh
sudo systemctl reboot
/bin/sh: line 2: /usr/bin/sudo: Input/output error
reboot
Failed to set wall message, ignoring: Access denied
Failed to reboot system via logind: Access denied
Failed to talk to init daemon.
su
/bin/sh: line 4: /usr/bin/su: Input/output error
su -c reboot
/bin/sh: line 5: /usr/bin/su: Input/output error
Last edited by schard (2021-04-16 22:55:18)
Inofficial first vice president of the Rust Evangelism Strike Force
Online
#!/bin/sh IFS=:; eval find $PATH $(printf ' -iname "*%s*"' $@) -exec basename "'{}' \;"
I'd suggest escaping $PATH and quoting $@ to allow for whitespace in them.
Also, find has `basename' built in.
IFS=:; eval find \$PATH $(printf ' -iname "*%s*"' "$@") -printf '%f\\n'
Offline
Yes, $@ should be quoted - though I'd certainly not have any executables in my PATH with spaces in their names. As for find's -printf flag, that will work on most arch systems, but it is a GNU extension to 'find' (it only works on my system with /bin/find). I don't see the purpose in escaping PATH. Can you elaborate on that?
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
Until I find some satisfying solution for the lack of Google sync stuff in Chromium, I have installed google-chrome from the AUR. The maintainers seem to be rather quick, but I don't want to bet on that. The Idea: If extra/chromium is newer than google-chrome on the AUR, then I want to know that.
You could try using a decent web browser, I suppose.
Managing AUR repos The Right Way -- aurpublish (now a standalone tool)
Offline
As for find's -printf flag, that will work on most arch systems, but it is a GNU extension to 'find' (it only works on my system with /bin/find).
I far too often forget that the GNU tools are non-standard.
I just noted that `basename' was quite slow for a larger number of files (i.e., calls). Fortunately, basename has a `-m' flag to allow for multiple arguments. Oh wait, that's a GNU extension.
I don't see the purpose in escaping PATH. Can you elaborate on that?
If $PATH is unescaped, it is expanded (including word-splitting on `:') before `eval' is called. `eval' then concatenates the words resulting from expansion, separated by whitespace. In particular, whitespace present in $PATH is now indistinguishible from whitespace originating from `:'. The result is finally regularly evaluated, as if it was passed to `sh -c'.
A simplified demonstration (ve: variable expansion, ee: `eval' evaluation):
$ VAR='1:2 3'
$ IFS=:
$ eval printf 'a:%s\\n' $VAR
ve-> eval printf 'a:%s\\n' 1 '2 3'
ee-> printf a:%s\\n 1 2 3
> a:1
> a:2
> a:3
$ eval printf 'b:%s\\n' \$VAR
ee-> printf b:%s\\n $VAR
ve-> printf b:%s\\n 1 '2 3'
> b:1
> b:2 3
To get more unexpected results, consider VAR='1 "2:3"' or VAR='$(rain)'.
Last edited by respiranto (2021-04-18 13:11:36)
Offline
Awebb wrote:Until I find some satisfying solution for the lack of Google sync stuff in Chromium, I have installed google-chrome from the AUR. The maintainers seem to be rather quick, but I don't want to bet on that. The Idea: If extra/chromium is newer than google-chrome on the AUR, then I want to know that.
You could try using a decent web browser, I suppose.
That would be fantastic, but as long as I'm hopping between 5+ devices and three operating systems, Chrome's sync and some Keepass offspring have so far been the only solution that isn't a maintenance nightmare. Firefox' sync doesn't work reliably on Android (at least for me), but that's where a good half of my web usage happens.
Offline
In particular, whitespace present in $PATH is now indistinguishible from whitespace originating from `:'.
Very true. Thanks. I suppose my bias (or good habit) shows in that spaces in executables in PATH is just something I'd avoid, spaces in components of PATH seem downright evil to me But it can happen and good code should cope with it.
(edit: typos, why the hell would I put apostrophes in plurals ... more coffee...)
Last edited by Trilby (2021-04-18 13:06:55)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
I wrote a script to list the contents of pacman databases as JSON for web applications.
It depends only on the standard library.
#! /usr/bin/env python3
#
# pjdb.py - JSON-ify pacman databases.
#
# (C) 2021 Richard Neumann <mail at richard dash neumann period de>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""JSON-ify pacman database."""
from datetime import datetime
from json import dumps
from pathlib import Path
from subprocess import CompletedProcess, run
from sys import argv
from tempfile import TemporaryDirectory
from typing import Iterator, Union
DESCFILE = 'desc'
INT_KEYS = {'%BUILDDATE%', '%CSIZE%', '%ISIZE%'}
LIST_KEYS = {'%DEPENDS%', '%MAKEDEPENDS%', '%OPTDEPENDS%'}
LIST_SEP = '\n'
ITEM_SEP = '\n\n'
KEY_VALUE_SEP = '\n'
TAR = '/usr/bin/tar'
KeyValuePair = tuple[str, Union[str, int]]
PackageDescription = tuple[str, KeyValuePair]
def _tar_xf(tarfile: Path, directory: Path) -> CompletedProcess:
"""Workaround for missing zstd support in Python's tar library."""
return run([TAR, 'xf', str(tarfile), '-C', str(directory)], check=True)
def kv_from_str(text: str) -> Iterator[KeyValuePair]:
"""Yields key / value pairs from a string."""
for item in text.split(ITEM_SEP):
if not item.strip():
continue
key, value = item.split(KEY_VALUE_SEP, maxsplit=1)
if key in INT_KEYS:
value = int(value)
elif key in LIST_KEYS:
value = value.split(LIST_SEP)
yield (key.replace('%', '').lower(), value)
def kv_from_file(filename: Path) -> Iterator[KeyValuePair]:
"""Yields key / value pairs from a file."""
with filename.open('r') as file:
yield from kv_from_str(file.read())
def pkg_from_dir(dirname: Path) -> PackageDescription:
"""Reads package information from a package directory."""
return (dirname.name, dict(kv_from_file(dirname / DESCFILE)))
def pkgs_from_dir(dirname: Path) -> Iterator[PackageDescription]:
"""Yields package descriptions."""
for pkgdir in dirname.iterdir():
yield pkg_from_dir(pkgdir)
def pkgs_from_db(filename: Path) -> Iterator[PackageDescription]:
"""Yields package descriptions from a database file."""
with TemporaryDirectory() as tmpd:
tmpd = Path(tmpd)
_tar_xf(filename, tmpd)
yield from pkgs_from_dir(tmpd)
def main():
"""Test the above stuff."""
databases = {}
for database in argv[1:]:
databases[database] = dict(pkgs_from_db(database))
print(dumps(databases, indent=2))
if __name__ == '__main__':
main()
Inofficial first vice president of the Rust Evangelism Strike Force
Online
Until I find some satisfying solution for the lack of Google sync stuff in Chromium, I have installed google-chrome from the AUR. The maintainers seem to be rather quick, but I don't want to bet on that. The Idea: If extra/chromium is newer than google-chrome on the AUR, then I want to know that.
To my surprise, google-chrome on the AUR got updated faster than chromium in the repos. Oh well, now I need a new non-issue to fix.
Offline
First post here on the forums. Here are 3 command line tools I wrote that I find myself using every once in a while. I'll just link the github urls to not post a massive wall of C.
$ pp "[LINE] " </some/file # Prepend text
[LINE] Some text
[LINE] Some more text
$ ap . </another/file # Append text
This file had no periods.
I like having periods.
$ cal | center - .gitignore
April 2021
Mo Tu We Th Fr Sa Su
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
# https://www.gutenberg.org/ has lots of material to test on.
test/
*.o
__mbuild.sh
.clang-format
center
$
Fair.
Offline
Why ap/pp and not just sed?
sed 's/^/[LINE] /' /some/file
sed 's/$/./' /another/file
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
Why ap/pp and not just sed?
sed 's/^/[LINE] /' /some/file sed 's/$/./' /another/file
I originally made pp both because I had some free time and nothing to do, and for the same reason I use `grep 'regex'` to match lines instead of `awk '/regex/'`. That being that why use a much more complex tool for something when I can have a much simpler one to do it instead. I obviously don't do that for everything, but I was prepending text in a couple of places so I thought "why not?". As for ap, that came about simply because I already made pp, and it only required a few extra lines of code to adapt it.
Fair.
Offline
Until the current issue with the Spotify download servers is resolved I created this script to install/update Spotify.
spotify_workaround
#!/usr/bin/env bash
set -e
#
# print messages in bold
#
function print {
echo -e '\n\t\033[1m' $1 '\033[0m\n'
}
#
# verify userid
#
if [ "$(whoami)" == "root" ] ; then
print "run this script as a user with sudo access because makepkg cannot be run as root"
exit
fi
#
# build spotify
#
curl -s https://download.spotify.com/debian/pubkey_0D811D58.gpg | gpg --import -
cd /tmp ; git clone https://aur.archlinux.org/spotify.git
cd spotify
echo "DLAGENTS=("http::/usr/bin/wget -r -np -nd -H %u")" >> PKGBUILD
makepkg --noconfirm -si && print "Spotify client setup complete"
Last edited by lenhuppe (2021-05-08 12:13:33)
"I'm suspicious of people who don't like dogs, but I trust a dog when it doesn't like a person." -- Bill Murray
Offline
The iscan-plugin-perfection-v370 package has an issue with checksums. I created this script to install the package and use my Epson scanner.
iscan_workaround
#!/usr/bin/env bash
set -e
#
# print messages in bold
#
function print {
echo -e '\n\t\033[1m' $1 '\033[0m\n'
}
#
# verify userid
#
if [ "$(whoami)" == "root" ] ; then
print "run this script as a user with sudo access because makepkg cannot be run as root"
exit
fi
#
# iscan-plugin-perfection-v370
#
print "Building epson scanner driver and utility"
cd /tmp ; git clone https://aur.archlinux.org/iscan-plugin-perfection-v370.git
cd iscan-plugin-perfection-v370
sed -i "s/sha256sums=('08026cedf7b13895526b5b6267e98f1ab2c5ed9eb417c565ef37cfd4787b7b65')/sha256sums=('7b44da1637432717aa2a2f7fd7dfbb04bcf486310484ce1c0a63ef5cb9968a32')/" PKGBUILD
makepkg --noconfirm -si && print "Image Scan for Epson setup complete"
"I'm suspicious of people who don't like dogs, but I trust a dog when it doesn't like a person." -- Bill Murray
Offline
I am using three monitors in a setup like this: [][ ][].
Works wonders, except when I want to play Spelunky. The 165hz refresh rate on the middle monitor is reduced to 60 because the side monitors are locked to 60. This script toggles those two monitors so I can play properly, and once I am done I press a button on the keyboard and it's restored again.
#!/bin/sh
# vim:ft=sh:
# toggle side panels in [][ ][] monitor setup
WIDTH=$(xrandr|grep -Po 'current.+, '|perl -pe 's/\w+\s(\d+) x.+$/$1/')
MONITOR_LEFT='--off'
MONITOR_RIGHT='--off'
if [ $WIDTH -eq 1920 ]; # side panels disabled
then
MONITOR_LEFT='--rotate left --right-of DP-4 --auto'
MONITOR_RIGHT='--rotate right --left-of DP-4 --auto'
xscreensaver -no-splash &
$RATPOISON -c 'echo screensaver enabled.'
else # disable side panels
MONITOR_LEFT='--off'
MONITOR_RIGHT='--off'
killall xscreensaver
$RATPOISON -c 'echo screensaver disabled.'
fi
xrandr --output HDMI-0 $MONITOR_LEFT --output DP-2 $MONITOR_RIGHT
catpoison -c restart
Offline