You are not logged in.

#3026 2017-05-26 18:05:23

adam_danischewski
Banned
Registered: 2016-05-06
Posts: 23
Website

Re: Post your handy self made command line utilities

Eschwartz wrote:
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

#3027 2017-05-26 18:49:41

Eschwartz
Member
Registered: 2014-08-08
Posts: 884

Re: Post your handy self made command line utilities

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)

Offline

#3028 2017-05-26 19:37:15

adam_danischewski
Banned
Registered: 2016-05-06
Posts: 23
Website

Re: Post your handy self made command line utilities

Eschwartz wrote:

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. smile

Offline

#3029 2017-05-26 20:13:34

Eschwartz
Member
Registered: 2014-08-08
Posts: 884

Re: Post your handy self made command line utilities

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)

Offline

#3030 2017-05-28 02:11:35

quequotion
Member
From: Oita, Japan
Registered: 2013-07-29
Posts: 558
Website

Re: Post your handy self made command line utilities

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)

Offline

#3031 2017-05-28 10:50:44

Trilby
Forum Moderator
From: Massachusetts, USA
Registered: 2011-11-29
Posts: 16,595
Website

Re: Post your handy self made command line utilities

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

Offline

#3032 2017-05-28 11:54:00

quequotion
Member
From: Oita, Japan
Registered: 2013-07-29
Posts: 558
Website

Re: Post your handy self made command line utilities

Trilby wrote:
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)

Offline

#3033 2017-05-28 14:16:25

Ropid
Member
Registered: 2015-03-09
Posts: 397

Re: Post your handy self made command line utilities

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

#3034 2017-05-28 15:16:08

Trilby
Forum Moderator
From: Massachusetts, USA
Registered: 2011-11-29
Posts: 16,595
Website

Re: Post your handy self made command line utilities

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 ...)

Offline

#3035 2017-05-28 15:50:05

Ropid
Member
Registered: 2015-03-09
Posts: 397

Re: Post your handy self made command line utilities

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

#3036 2017-05-28 20:08:39

Alad
Wiki Admin/IRC Op
Registered: 2014-05-04
Posts: 1,508

Re: Post your handy self made command line utilities

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
User:Alad

Offline

#3037 2017-05-28 22:02:55

Ropid
Member
Registered: 2015-03-09
Posts: 397

Re: Post your handy self made command line utilities

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

#3038 2017-05-29 05:17:03

quequotion
Member
From: Oita, Japan
Registered: 2013-07-29
Posts: 558
Website

Re: Post your handy self made command line utilities

Ropid wrote:

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 smile

Offline

#3039 2017-05-29 05:40:38

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 22,162
Website

Re: Post your handy self made command line utilities

This would probably be much better handled by expac.


Arch + dwm   •   Mercurial repos  •   Github

Registered Linux User #482438

Offline

#3040 2017-05-29 07:16:11

Alad
Wiki Admin/IRC Op
Registered: 2014-05-04
Posts: 1,508

Re: Post your handy self made command line utilities

jasonwryan wrote:

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
User:Alad

Offline

#3041 2017-05-29 10:19:38

Trilby
Forum Moderator
From: Massachusetts, USA
Registered: 2011-11-29
Posts: 16,595
Website

Re: Post your handy self made command line utilities

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).

Offline

#3042 2017-05-29 10:50:30

Alad
Wiki Admin/IRC Op
Registered: 2014-05-04
Posts: 1,508

Re: Post your handy self made command line utilities

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
User:Alad

Offline

#3043 2017-05-31 11:01:24

Ambrevar
Trusted User (TU)
Registered: 2011-08-14
Posts: 187
Website

Re: Post your handy self made command line utilities

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

#3044 2017-05-31 11:44:46

Trilby
Forum Moderator
From: Massachusetts, USA
Registered: 2011-11-29
Posts: 16,595
Website

Re: Post your handy self made command line utilities

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

Offline

#3045 2017-05-31 17:33:43

Ambrevar
Trusted User (TU)
Registered: 2011-08-14
Posts: 187
Website

Re: Post your handy self made command line utilities

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

#3046 2017-05-31 18:40:17

Trilby
Forum Moderator
From: Massachusetts, USA
Registered: 2011-11-29
Posts: 16,595
Website

Re: Post your handy self made command line utilities

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.

Offline

#3047 2017-06-01 15:44:24

Ambrevar
Trusted User (TU)
Registered: 2011-08-14
Posts: 187
Website

Re: Post your handy self made command line utilities

Thanks for digging out the details!

Offline

#3048 2017-06-12 00:37:50

leo_gott82
Member
From: Buenos Aires
Registered: 2016-08-29
Posts: 13

Re: Post your handy self made command line utilities

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

Board footer

Powered by FluxBB