Here I’ll showcase some of the more powerful examples of exec-cmd, my parameterized aliasing system I leverage for all sorts of frequent use.
See the repository README for the basic usage.
All the below use cases originate from the repository included commands.
Overview
- Send a quick command line email
- Search for a custom, multi-line text record
- Custom word-count
- YouTube
- Git
- Imagemagick batch resize
- Sync your config files with a repository
Send a quick command line email
The following definition sends an email from the console via mutt. Note that any of the aliases emailsend
, sendmail
, or sm
may be used.
emailsend,sendmail,sm mutt -s !!subject !!recepient <<< !!body
Invoke the command with no arguments, to see the expected syntax:
$ ec sm
Required parameters: !!subject !!recepient !!body
And a working example, where ‘me’ is a mutt alias for my email address:
$ ec sm "exec-cmd test" me "Hello world"
Search for a custom, multi-line text record
The following searches the standard input for an entire (multi-line) text record. The record returned is one whose
- header matches the regular expression
!!rec_start_regex
- contents match the expression
!!pattern
.
search_txt_record,srl pattern=!!pattern && \
sed -n "/!!rec_start_regex/{x;/$pattern/Ip;d}; \${x;G;/$pattern/Ip}; {H}"
(Perhaps not the most optimal sed usage, but it gets the job done.)
The use should become clearer with the following two commands that stack on top of the above. We now only expect one parameter, the !!pattern
:
search_txt_list,stl %self% search_txt_record !!pattern '^\w'
search_md_section,smd %self% search_txt_record !!pattern '^#'
The first searches indented text list records, each beginning at the 0th column, with the remainder containing some non-word leading character (ex: space, hyphen).
The second searches a markdown section beginning with a ‘#’ character. A record continues until we encounter another leading ‘#’, which thus deliniates a new section.
An incredibly simple example of search_txt_list
:
We first create input.txt
with our input,
one
- alpha
- beta
- charlie
- lambda
two
delta
echo
felix
lambda
three
- gamma
- hydra
- ingrid
- lambda
And then the invocation:
$ ec stl
Required parameters: !!pattern
$ ec stl 'echo' < input.txt
two
delta
echo
felix
lambda
Lastly, let’s demonstrate a two-level conjunctive search, that is, the searching of a record matching !!pattern1
and !!pattern2
.
Were this a scalable solution up to any n levels, we would require a more elaborate routine. However, for a pragmatic two-level case, the following hack of pure piping wizardry does the trick:
stl2 %self% stl !!pattern1 | %self% stl !!pattern2
Note that ‘lambda’ appears in every record of the same input file, but ‘hydra’ strictly in the last:
$ ec stl2 lambda hydra < input.txt
three
- gamma
- hydra
- ingrid
- lambda
Custom word-count
The following returns the count of !!num_top_results
number of most frequent words of at least !!min_chars
number of characters, each with the respective count:
word_count,wc tr -cs A-Za-z '\012' | tr A-Z a-z | \
egrep "\<.{!!min_chars,}\>" | sort | \
uniq -c | sort -nr | head -!!num_top_results
YouTube
View a YouTube URL !!url
via mpv of a maximum height of !!maxheight
:
youtube,yt maxheight=!!maxheight && \
mpv --ytdl-format="bestvideo[height<=$maxheight]+bestaudio/best[height<=$maxheight]" \
!!url
Git
List the urls of all Git repositories situated under the path !!root
:
git_rep_list find !!root -regex '.*\.git/config*' -exec cat {} \; \
| sed -n 's/.*url = \(.*\)/\1/p'
Extract a repository subfolder to a fresh repository, all contained files now at the root, history preserved:
git_split_dir newrep=!!newrep_dir && \
dir_prefix=!!dir_prefix && \
git subtree split --prefix=$dir_prefix --branch=split && \
git init --bare $newrep && \
git push $newrep split:master && \
git branch -D split && \
echo "Created bare rep $newrep." && \
echo "Next: 'rm -r' or filter out $dir_prefix/ "
The above routine:
- Takes parameters
!!newrep_dir
- the path to a fresh repository!!dir_prefix
- the subfolder prefix in the original repository
- Extracts the subfolder into a temporary branch called ‘split’
- Initializes a new, bare repository indicated by
!!newrep_dir
- Pushes the branch ‘split’ onto the new repository
- Deletes the temporary branch
- Leaves the original repository intact, letting you manually delete/handle the extracted subfolder however you please.
Lastly, the following command eliminates all trace of a file !!filename
within the repository, along with the related history:
git_elim_file_hist git filter-branch -f --index-filter \
"git rm --cached --ignore-unmatch !!filename" HEAD
Imagemagick batch resize
Shrink an image or a set of images to a maximum dimension size of !!max_size
, maintaining the aspect ratio:
img_shrink_if_gt size=!!max_size && mogrify "!!pattern[$size""x""$size"">]"
For example, ec img_shrink_if_gt 1024 '*.jpg'
shrinks all jpegs in the current directory to the maximum dimensions of 1024x1024, resizing the smaller of the dimensions appropriately to maintain the aspect ratio.
Sync your config files with a repository
In the example commands you’ll find a sync
routine that I will not here reproduce. It effectively invokes rsync with a series of handy parameters.
Of interest is the following command stacked on top of sync
to restrict the synchronization of !!src
to only the files contained within !!dest
:
sync_existing_only src="!!src" dest="!!dest" && \
%self% sync "$src" "$dest" \
--files-from=<(find "$dest" -type f -printf '%P\n')
It does this, moreover, not using the --existing
rsync parameter, but the safer, faster, and more explicit --files-from
, which we build via a named-pipe call to find
.
This is handy, for instance, when you wish to synchronize a series of configuration files with a Git repository.
Suppose your repository exists in $HOME/config-rep
. First, manually copy all config files from under your home directory to config-rep
, maintaining the same directory structure.
The following exec-cmd
command (not included in the repository) then synchronizes strictly the files contained within config-rep
:
sync_config_rep %self% sync_existing_only ~/ "$HOME/config-rep/"
(No parameters are necessary upon the call to ec sync_config_rep
.)
Questions, comments? Connect.