Today’s random tech tip of the day – how to check whether you have modifications in a bunch of different locally cloned git repos:
⯠for x in *; do echo $x ; ( cd $x; git status -s ); done contentsvc jobsvc M supervisor.conf profilesvc
Today’s random tech tip of the day – how to check whether you have modifications in a bunch of different locally cloned git repos:
⯠for x in *; do echo $x ; ( cd $x; git status -s ); done contentsvc jobsvc M supervisor.conf profilesvc
I’ve sometimes wished that the UNIX touch
command had the same -p option as mkdir
. With a little bit of scripting, it can:
#!/bin/sh mkdir="/bin/mkdir" touch="/usr/bin/touch" for arg in $*; do if [ "$arg" = "-p" ]; then opt_p=true continue fi if [ "$opt_p" = "true" ]; then $mkdir -p $(dirname $arg) && $touch $arg else $touch $arg fi done
Here’s a useful tip on how to make bash check the window size between commands.
shopt -s checkwinsize
The other day I wanted to enable IP forwarding on my Linux box (so that it could forward packets from a tun virtual interface being used by VTun to the physical interface connected to my home network).
I looked up it up and it turns out that it’s a simple setting in a file in the /proc
filesystem, so I did what seemed obvious and logical at the time:
marca:~$ sudo echo "1" > /proc/sys/net/ipv4/ip_forward -bash: /proc/sys/net/ipv4/ip_forward: Permission denied
I took this to mean that my kernel was not compiled with ip_forward support and then wasted a bunch of time building a new kernel.
Finally, it dawned on me. Duh. The echo
command is a shell built-in so sudo has no effect.
I didn’t need a new kernel. All I had to do was:
marc:~$ sudo bash root:~# sudo echo "1" > /proc/sys/net/ipv4/ip_forward root:~# cat /proc/sys/net/ipv4/ip_forward 1
or even:
marc:~$ sudo sh -c 'echo "1" > /proc/sys/net/ipv4/ip_forward'
Sigh.
I thought of the idea of preventing this in the future by defining a bash function that detects builtins:
function sudo() { if [ $(type -t "$1") == "builtin" ]; then echo "sudo bash function: ERROR - \"$1\" is a shell builtin" 1>&2 return 1 fi command sudo "$@" }
which works for some cases but unfortunately doesn’t help for the case above, because the redirection permissions are checked before the function is executed. Sigh.
I’m reminded today of Sniglets. I grew up in the 1980s watching lots of HBO, so Rich Hall’s little segments from Not Necessarily the News occupy a special place in some dark corner of my cerebrum. I can still remember to this day:
I just thought of a sniglet of my own. It’s a term for when you spend a couple of hours writing fancy little bash functions that do really specialized things that are fun but perhaps of questionable use.
I call this: “bashturbation”.
Let’s say we want to write a command that allows you to take the output of the previous command and stick it in your editor so you can page through it, save it, email it, etc.
One way to do it is with bash’s “process substitution” feature. Try this:
$ ls -l $ cat <($(tail -1 $HISTFILE)) | vim -
One problem with this is it won’t work if you change “vim” to “emacs”, because Emacs doesn’t like to read stdin. I tried all kinds of stuff including “emacs -nw -t /dev/tty /dev/stdin” and such.
Well, here’s an even more general solution:
with-temp-file () { local _prefix=$1; shift local _tmpfile_var=$1 ; shift local ${_tmpfile_var}=$(mktemp -t ${_prefix}) eval local _tmpfile_value=\${$_tmpfile_var} eval "$@" rm ${_tmpfile_value} } edlo () { with-temp-file "edlo" tmpfile \ '$(tail -1 $HISTFILE) > $tmpfile && $EDITOR $tmpfile' }
Actually for bash versions 2 and up, it turns out we can clean this up a tad using the new syntax for indirect references to variables:
--- edlo.sh.2006-04-29-152010 Sat Apr 29 15:19:53 2006 +++ edlo.sh Sat Apr 29 15:25:11 2006 @@ -3,7 +3,7 @@ local _prefix=$1; shift local _tmpfile_var=$1 ; shift local ${_tmpfile_var}=$(mktemp -t ${_prefix}) - eval local _tmpfile_value=\${$_tmpfile_var} + local _tmpfile_value=${!_tmpfile_var} eval "$@" rm ${_tmpfile_value} }
This should work in any editor, including X11 editors since we’re not using stdin. And the with-temp-file
function is a general utility function that could be used for other stuff. Here’s another function that uses it:
eoo () { local _cmd="$@"; with-temp-file "eoo" tmpfile '$_cmd > $tmpfile && $EDITOR $tmpfile' }
This one is when you already know that you want to capture the output of a particular command – e.g.:
$ eoo ls -l $ eoo finger
Enjoy.
function _globdo { local arg="$1" local dir=$(dirname $arg) local base=$(basename $arg) shift find $dir -name $base -exec "$@" {} \; set +f } alias globdo='set -f; _globdo'
The function/alias combo is get around automatic globbing and make it possible to specify glob patterns without having to quote them. See Simon Tathams’s Magic Aliases article for more info.
Examples of usage:
globdo *.c grep -H union globdo /some/tree sed -i .bak 's/foo/bar/g'
Some tools like GNU grep already have recursive capabilities, but what I like about this approach is that it basically gives you recursive capabilities for all your tools and it does it in a consistent manner. To me it’s nicely in line with the Unix philosophy of having small tools that do particular tasks well and then stringing them together to create more complex behavior.
I hope that you find it useful. Comment if you have any improvements…