You are not logged in.
adam_danischewski wrote:If you need to copy things to multiple locations:
alias cpm='_() { src="${1%/}"; shift; printf "\"%s\" " "$@" | xargs -n 1 cp -vR "${src}"; }; _'
Why not just use a function "cpm()" directly???
Force of habit - you can break it out and run it as a function cpm(). I've been using aliases for a long time and I have utilities built for handling and pulling data from my aliases file that I don't need/want to change at the moment.
$> mkdir -p /tmp/test;cd /tmp/test;cpm(){ src="${1%/}"; shift; printf "\"%s\" " "$@" | xargs -n 1 cp -vR "${src}";}
$>touch file.txt;mkdir -p {a..d}
$>cpm file.txt {a..d}
‘file.txt’ -> ‘a/file.txt’
‘file.txt’ -> ‘b/file.txt’
‘file.txt’ -> ‘c/file.txt’
‘file.txt’ -> ‘d/file.txt’
Offline
Also, no need for all that xargs and printf clutter. And, why are you stripping dirnames from the source file -- is this specifically meant to fail in an unidentified manner when copying things that aren't located in cwd?
cpm() {
local i
for i in "${@:2}"; do
cp -vR "$1" "$i"
done
}
Last edited by eschwartz (2017-05-26 18:50:22)
Managing AUR repos The Right Way -- aurpublish (now a standalone tool)
Offline
Also, no need for all that xargs and printf clutter
cpm() { local i for i in "${@:2}"; do cp -vR "$1" "$i" done }
No need for loops, when you have the elegance of xargs.
Offline
I'd say handling it in pure bash is more elegant than shelling out for no good reason. Especially when you then have to printf and format argv all over again over stdin, using comparatively arcane escaping (whereas bash knows how to expand and tokenize "$@" natively).
xargs is a useful tool in a scripter's arsenal, not some sort of goal in and of itself. Using xargs does not win you internet points for elegance...
Last edited by eschwartz (2017-05-26 20:15:08)
Managing AUR repos The Right Way -- aurpublish (now a standalone tool)
Offline
Been having "shutdown sickness" lately*. It seems to be by design. I'd rather not wait until every desktop application in development is updated to play nice with systemd.
Found this neat idea and expanded on it:
#!/bin/bash
#Reboot or shutdown
[[ "${1}" == "reboot" || "${1}" == "-r" ]] && SEQUENCE=(s u b)
[[ "${SEQUENCE}" ]] || SEQUENCE=(s u o)
for i in "${SEQUENCE[@]}"; do sleep 3; printf "${i}" > /proc/sysrq-trigger; done
Is three seconds long enough?
*"Shutdown sickness" is how I have been describing this symptom (extremely delayed shutdown) since I first encountered it, in Windows 95.
::EDIT::
Bonus: Get the total size of all installed software package files (in GiB):
printf "$(echo "$(TOTAL=0; for i in $(pacman -Qi | grep "MiB" | sed 's/[^0-9,.]*//g' | xargs -n1); do TOTAL="$(echo ${i}+${TOTAL} | bc)"; done; echo "scale=2;${TOTAL}/1024" | bc)+$(TOTAL=0; for i in $(pacman -Qi | grep "KiB" | sed 's/[^0-9,.]*//g' | xargs -n1); do TOTAL="$(echo ${i}+${TOTAL} | bc)"; done; echo "scale=2;${TOTAL}/1024/1024" | bc)" | bc) GiB\n"
Has this been done before? I hope there's a more efficient way.
>9.35 GiB!
Last edited by quequotion (2017-05-28 10:21:19)
makepkg-optimize · indicator-powersave · pantheon-{3d,lite} · {pantheon,higan}-qq
Offline
There is definitely a more efficient way - that is a ridiculous number of pipes, subshells, and repeated xargs, bc, grep calls. There are many incremental simplifications that can be made, but why not just sum the sizes directly:
awk '/%SIZE%/ {getline; size+=$1; } END { print size / (1024 * 1024) " MiB"; }' /var/lib/pacman/local/*/desc
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
awk '/%SIZE%/ {getline; size+=$1; } END { print size / (1024 * 1024) " MiB"; }' /var/lib/pacman/local/*/desc
Marvelously shorter, and more accurate (pacman -Qi's output is approximate). One more "* 1024" for GiB:
awk '/%SIZE%/ {getline; size+=$1; } END { print size / (1024**3) " GiB"; }' /var/lib/pacman/local/*/desc
Last edited by quequotion (2017-05-28 12:18:00)
makepkg-optimize · indicator-powersave · pantheon-{3d,lite} · {pantheon,higan}-qq
Offline
Following the original idea about going through "pacman -Qi", that could have been done more efficient like this:
pacman -Qi |
sed -nr '/^Installed Size *: / { s///; s/ //; s/B$//; p }' |
numfmt --from=auto --format=%.0f |
awk '{ total += $1 } END{ print total }' |
numfmt --to=iec-i --format=%.2f --suffix=B
Offline
If you're going to parse pacman output and use awk anyways, then sed serves no purpose - neither does numfmt really:
pacman -Qi | awk '/Installed Size/ { sum[$5]+=$4; } END { print sum["MiB"] + sum["KiB"] / 1024; }'
I left off the printing of sum["B"] as it would be divided by 1024^2 and not provide any change in the displayed number. I've also left out sum["GiB"] as I don't know of any packages with GiB installed sizes, but they may exist - this could be added to the print (sum["GiB"] * 1024 ...)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
The solution with the sed + numfmt + awk + numfmt actually seems faster here for me. Nearly all of the time disappears into "pacman -Qi" anyways, but I also tried it with pacman's output saved into a file to test just awk etc.:
$ pacman -Qi > pacman.txt
$ time { for x in {1..100}; do <pacman.txt awk '/Installed Size/ { sum[$5]+=$4; } END { print sum["MiB"] + sum["KiB"] / 1024; }'; done; }
...
11597.9
11597.9
11597.9
real 0m0.727s
user 0m0.699s
sys 0m0.051s
$ time { for x in {1..100}; do <pacman.txt sed -nr '/^Installed Size *: / { s///; s/ //; s/B$//; p }' | numfmt --from=auto --format=%.0f | awk '{ total += $1 } END{ print total }' | numfmt --to=iec-i --format=%.2f --suffix=B; done; }
...
11.33GiB
11.33GiB
11.33GiB
real 0m0.628s
user 0m0.964s
sys 0m0.070s
Looking at that result, I guess it's somehow faster here because it's using more than one CPU core?
About the "GiB", I do have a package "ghc" that's 1.1G, but pacman prints it as 1146.92 MiB.
Last edited by Ropid (2017-05-28 15:52:56)
Offline
So, you get a performance increase of hardly more than a measuring error for a code line that's twice as long and 10 times harder to understand. Not a great deal.
Mods are just community members who have the occasionally necessary option to move threads around and edit posts. -- Trilby
Offline
I think it will actually all run the same in reality because your stuff will get run in parallel to "pacman -Qi" doing its thing. What's best depends on the person, I guess. I wouldn't have come up with that hash thingy for awk by myself to deal with the MiB and KiB, but I used numfmt before and have practice with regex.
Offline
Following the original idea about going through "pacman -Qi", that could have been done more efficient like this:
pacman -Qi | sed -nr '/^Installed Size *: / { s///; s/ //; s/B$//; p }' | numfmt --from=auto --format=%.0f | awk '{ total += $1 } END{ print total }' | numfmt --to=iec-i --format=%.2f --suffix=B
At first I used "pacman -Qi" because It didn't occur to me to access the database directly as Tribily demonstrated; it seemed logical to get this information from pacman. Unfortunately pacman provides numbers in various units {KiB,MiB} and rounds to two decimal places. Getting the size in bytes from the database is more precise and, by not loading the whole database, probably more efficient--but I'm curious if the calculations may actually take longer than using the rounded numbers provided by "pacman -Qi"
Ideally I would have pacman offer the size in bytes, or at least consistent units, and be able to write a more simple script for "pacman -Qi", or add functionality to pacman to output the total itself, because I like the idea of getting this information from the package manager executable; but I'm not about to fork pacman (again) over it
makepkg-optimize · indicator-powersave · pantheon-{3d,lite} · {pantheon,higan}-qq
Offline
This would probably be much better handled by expac.
Offline
This would probably be much better handled by expac.
$ expac -Q '%m' -H M | datamash -W sum 1
1972.25
Note: the "exact" value is 1972.298828125, which can be retrieved by removing the -H option and dividing by 1024^2.
Last edited by Alad (2017-05-29 07:21:30)
Mods are just community members who have the occasionally necessary option to move threads around and edit posts. -- Trilby
Offline
My version from post 3031 is still consistently faster than the expact approach for me (though I fully agree parsing pacman output like the above approaches is silly, that is what expac is for).
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
Yeah, expac is fairly slow on the first run (before things are cached). A concern when using it in scripts - for me at least - but for interactive use the shortness is nice. One less alias to define...
Last edited by Alad (2017-05-29 10:53:05)
Mods are just community members who have the occasionally necessary option to move threads around and edit posts. -- Trilby
Offline
I would like a shell command to print the date of various locations around the world, similar to Emacs' display-time-world.
I've come up with this POSIX shell script:
#!/bin/sh
set -- \
UTC UTC \
Europe/Paris "France Germany" \
Asia/Calcutta India \
etc. ...
while [ $# -gt 0 ]; do
date=$(TZ="$1" date)
printf "%s\t%s\n" "$date" "$2"
shift 2
done
Am I re-inventing the wheel? Anything simpler?
Last edited by Ambrevar (2017-05-31 11:07:01)
Offline
Not sure if there's an existing wheel being reinvented, but you could avoid the subshells:
...
while [ $# -gt 0 ]; do
TZ="$1" date "+%a %b %d %R:%S %Z %Y%t$2"
shift 2
done
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
True, and even simpler:
TZ="$1" date "+%c%t$2"
I just realized however that date prints in a format different from %c, i.e. it does not respect my locale.
> date
Wed May 31 18:30:57 CET 2017
> date +%c
Wed 31 May 2017 06:31:00 PM CET
Is this the expected behaviour?
Offline
I was thinking about suggesting "+%c%t$2" but it is a different format. Both `date` and `date +%c` should respect locale, and both of your outputs are in the same locale, they are just different formats (different order of information and one on 24-hour one on 12).
Although, I suppose while my format string is equivalent to the default in every case I can find, it is not the identical format string according to the `info` page. It should be "+%a %b %e %H:%M:%S %Z %Y%t$2" if LC_DATE is not set.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
Thanks for digging out the details!
Offline
Since I prefer to use the mouse as little as possible, I wrote this lil' script (depends on wmctrl and xdotool) to handle windows directly through the keyboard. In this way, you only have to press a few keys in order to iconify, unminimize or close a running window. Hope it'll be useful for some of you. Feel free to modifiy or add whatever you want, for instance, a maximize function (didn't do it myself 'cause I don't like maximized windows).
#!/bin/bash
#Little window manager that allows you to perform basic operations on windows
#It depends on wmctrl and xdotool
###Colors####
red="\033[1;31m"
green="\033[1;32m"
yellow="\033[1;33m"
blue="\033[1;34m"
magenta="\033[1;35m"
cyan="\033[1;36m"
d_cyan="\033[0;36m"
white="\033[1;37m"
d_white="\033[0;37m"
nc="\033[0m"
function help ()
{
clear
echo -e "${cyan} LilWinMan 1.1 (2016)$nc\n"
echo -e "LilWinMan doesn't take arguments, but works only interactively."
echo -e "${white}Usage: $nc"
echo -e "Type the number of the listed window followed by the key identifyng the action you \
want to perform over the selected window."
echo -e "Action keys are: \n'${yellow}i$nc' - ${white}iconify$nc \n'${yellow}u$nc' - ${white}unminimize$nc or raise a window\n'${yellow}c$nc' - ${white}close$nc \
gracefully \n'${yellow}k$nc' - ${white}kill$nc a window"
echo -e "E.g.: '${yellow}3 c$nc' will close the third listed window"
echo -e "The program also allows you to ${white}run a command$nc instead of managing some opened window. \
For instance, if you want to open the IceApe web browser, you simply has to type 'iceape', press enter, and \
IceApe will show up.\nTo show this ${white}help$nc type '${yellow}h$nc' or '${yellow}help$nc'."
read -n1 -r -p "Press any key to continue..." key && clear
return
}
function show_windows ()
{
mapfile -t windows < <(wmctrl -lp | awk '{$2=$3=$4=""; print $0}' | sed 's/ / /g')
for (( i=0;i<${#windows[@]};i++)); do
###print only the win_name
#Tell LilWinMan not to display its own window
if ! [[ ${windows[$i]} == *"LilWinMan" ]]; then
##get window's state
state="$(xprop -id $(echo "${windows[$i]}" | awk '{print $1}') | grep "window state" | awk '{print $3}')"
if [[ $state == "Iconic" ]]; then
echo -e "${d_white}$((i+1)) - ${d_cyan}$(echo "${windows[$i]}" | awk '{$1=""; print $0}' | sed 's/ / /g')$nc"
else
echo -e "${white}$((i+1)) - ${cyan}$(echo "${windows[$i]}" | awk '{$1=""; print $0}' | sed 's/ / /g')$nc"
fi
fi
done
##Display possible actions###
echo -ne "\n${white}Usage:$nc\nwindow_id ${yellow}[i]${nc}conify, ${yellow}[u]${nc}nminimize, ${yellow}[c]${nc}lose, ${yellow}[h]${nc}elp: "
##save input in an array: first arg is win number, the second is action###
read -a input
case ${input[0]} in
q|quit|exit) exit 0;;
h|help) help && show_windows;;
#if input is not a number...
*) ! [[ ${input[0]} =~ ^-?[0-9]+$ ]] && eval ${input[@]} 2>/dev/null && exit 0;;
#eval allows you to take the content of a variable and run it as a command
#Note: whenever the command run by eval fails (or it doesn't exist), the error is displayed
#in the screen, the exit command never happens, and therefore the script goes on to the next
#condition (line 47), and then to the next (line 49), where it fails and exits.
#Note2: the workaround was to repeat (in line 45) the condition that tests whether input is
#a number (line 37) after the case sentence.
esac
}
show_windows
#if not a number...
! [[ ${input[0]} =~ ^-?[0-9]+$ ]] && echo -e "${red}Program doesn't exist!$nc" && sleep 1.4 && exit 0
#if a number, check whether it's not greater than the total amount of windows
[[ "${input[0]}" -gt "${#windows[@]}" ]] && echo -ne "${red}Invalid window!$nc" && sleep 1.3 && exit 0
###check if second argument has been passed
[[ -z ${input[1]} ]] && echo -e "${white}You must specify an action.$nc" && sleep 1.5 && exit 0
###save the win_id
win_id=$(echo "${windows[$((input[0]-1))]}" | awk '{print $1}')
###read the second argument and run the corresponing command##
case ${input[1]} in
#neither wcmtrl now xdotool by themselves are able to iconify (minimize) a window neither by
#name nor by id, so that the workaround is to first unminimize the window to be minimized with
#wmctrl and then to minimize the active window with xdotool
i) wmctrl -ia $win_id && xdotool getactivewindow windowminimize;;
u) wmctrl -ia $win_id;;
c) wmctrl -ic $win_id;;
#k option should be used only when the window doesn't respond and cannot be gracefully closed.
#Don't list this option in screen, but only in help.
k) wmctrl -ia $win_id && xdotool getactivewindow windowkill;;
*) echo -e "${red}Wrong option!$nc" && sleep 1.4 && exit 0
esac
exit 0
It could be a good idea to call this script (as an argument for a terminal) with a keyboard shortcut. In Openbox, it would be something like this:
<keybind key="C-x">
<action name="Execute">
<command>aterm -name "LilWinMan" -title "LilWinMan" -geometry 50x18+430+120 -e /path/to/the/script</command>
</action>
</keybind>
Btw, this thread rocks! Thank you all.
Last edited by leo_gott82 (2017-06-12 00:57:51)
Der Mensch weiss nur von Gott, insofern Gott im Menschen von sich selbst weiss.' (Hegel)
Offline
Here's a small utility I wrote for detecting which version of GCC (or FPC or OCaml) that was used for compiling an ELF executable.
It also works for stripped executables and it can detect the architecture and little endian/big endian order.
Example:
$ elfinfo /usr/bin/ls
/usr/bin/ls: stripped=true, compiler=GCC 6.3.1, byteorder=LittleEndian, machine=Advanced Micro Devices x86-64
Homepage: ELFinfo
Latest release: elfinfo-0.5.tar.xz
AUR package: elfinfo
Offline
My alarm clock is annoying. It makes an annoying sound that my unconscious mind just wants to stop, so I tend to hit the snooze after partially waking up, but not enough to actually get up. It has a 9-minute snooze, which apparently is just a terrible thing for my sleep cycle or something.
Turns out my computer makes a better alarm clock. These scripts can definitely use some polish, but I've been waking up earlier, feeling much more rested.
#!/usr/bin/env rc
# ~/local/bin/alarmclock: wake the computer up at the given time,
# defaulting to 5:55 a.m.
if (~ $#1 0) {
when='tomorrow 5:55'
}
if not {
when=$1
}
sudo rtcwake -m mem -t `{u date +%s -d $when} && alarm
#!/usr/bin/env rc
# alarm: pick a random song and start playing it quietly, getting
# louder over time
# Pick & play a random album.
# The random selector almost never fails, so even one retry-on-fail
# should mean it always works.
mpc randalbum || mpc randalbum || mpc randalbum
# In case it comes up with a really short one
mpc repeat on
# ALSA's way of denoting volume is *weird*. amixer's 50% = alsamixer's 23
amixer set Master 50%
# FIXME: testing for a file is a stupid way to reclaim control
# of the volume without stopping the music.
while (test ! -f /tmp/stop && mpc status | grep playing) {
amixer set Master 1+
sleep 120
}
Offline