<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>sglavoie.com – Tag: Linux</title><link>https://www.sglavoie.com/tags/linux/</link><description>Posts and writings by Sébastien Lavoie. Customization setups and articles on productivity for developers who like minimalism.</description><language>en</language><atom:link href="https://www.sglavoie.com/tags/linux/feed.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Sun, 05 Apr 2020 12:14:00 -0500</lastBuildDate><item><title>Tip the Scales in Times of Instability With the Rock-Solid Debian</title><link>https://www.sglavoie.com/posts/tip-the-scales-in-times-of-instability-with-the-rock-solid-debian/</link><description>Desperate times call for the best Linux experience possible… And in my experience so far, the Debian distribution with the Xfce desktop environment or with the even lighter alternative i3 tiling window manager makes for a very smooth ride.</description><content:encoded>&lt;hr&gt;
&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m familiar with Linux distribution hopping, having tried out many options over the years, starting around the time Mandrake 9.2 was popular back in 2003, then switching to a few others including Ubuntu, KNOPPIX, Fedora, Xubuntu, openSUSE, Kubuntu, Mint, Manjaro, Mandriva&amp;hellip; And of course Debian along the way, which undoubtedly used to be relatively harder to get started with.&lt;/p&gt;
&lt;p&gt;My heart has also been stirred by different desktop environments and window managers, from more user-friendly/feature-rich solutions such as KDE, GNOME (along with Unity when it was still a thing), Xfce and Cinnamon to an arguably more obscure selection comprising Openbox, Fluxbox, Enlightenment, Awesome WM, dwm, i3 and bspwm.&lt;/p&gt;
&lt;p&gt;I haven&amp;rsquo;t tried everything that&amp;rsquo;s out there (XMonad being one such &lt;em&gt;esoteric&lt;/em&gt; possibility), but I&amp;rsquo;ve come to realize that what matters most to me is a great balance of stability and usability, allowing to be more focused on any given task at end and therefore leading to increased productivity. For this reason, I recently turned back to a fantastic combo: Debian with an Xfce base and the i3 tiling window manager.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="why-debian"&gt;Why Debian?&lt;/h2&gt;
&lt;h2 id="stability-and-reliability"&gt;Stability and Reliability&lt;/h2&gt;
&lt;p&gt;Debian has always been to me the father figure of stability in the Linux world. Countless servers have run on Debian and continue to do so for good reason: it just works once it is properly set up. I have had some bad luck with other Debian-based distributions like Ubuntu and Linux Mint which strive to be easier to use but remain easier to break, being a bit more bleeding edge and sometimes bloated too with tons of software I don&amp;rsquo;t really need. Fedora, although I like its philosophy and style very much, has always lead to hardware issues on my apparently less-than-ideal machines. Manjaro has been pleasant and easy to use, but Arch feels like the &lt;em&gt;right&lt;/em&gt; choice if one is to build a custom system from scratch. It does take a good amount of time to get things going on such a distribution and usually a good dose of maintenance too, which brought me to seek less time-consuming options. For stability and reliability, Debian is hard to beat in my experience.&lt;/p&gt;
&lt;h2 id="marvelous-package-manager"&gt;Marvelous Package Manager&lt;/h2&gt;
&lt;p&gt;I have always found the package manager on Debian (and derivatives) to be easier to use than alternatives like &lt;code&gt;yum&lt;/code&gt;, &lt;code&gt;DNF&lt;/code&gt; or &lt;code&gt;urpmi&lt;/code&gt; for RPM packages. The &lt;code&gt;pacman&lt;/code&gt; package manager available on Arch-based systems is truly excellent and powerful, but I simply find &lt;code&gt;apt&lt;/code&gt; to be more intuitive after using it for a lot longer.&lt;/p&gt;
&lt;h2 id="it-just-wont-break"&gt;It Just Won&amp;rsquo;t Break&lt;/h2&gt;
&lt;p&gt;Sitting on the bleeding edge is fun and sometimes even rewarding when things finally work as expected, but I have seen that it doesn&amp;rsquo;t stay that way forever. Big updates, sometimes relatively frequent ones, can leave the system in an unusable state. It&amp;rsquo;s often a minor annoyance to fix, but that just doesn&amp;rsquo;t happen on Debian, where packages are vetted mainly for their legendary stability before releasing them. They are indeed quite a bit older than what can be found on other distributions. It&amp;rsquo;s the price to pay, but I came to the conclusion that it&amp;rsquo;s worth it if you&amp;rsquo;re looking to get things done in the long run.&lt;/p&gt;
&lt;figure&gt;
 &lt;a href="https://www.sglavoie.com/images/posts/0020_stable_system_debian/debian_xfce.png"&gt;&lt;img src="https://www.sglavoie.com/images/posts/0020_stable_system_debian/debian_xfce.png" alt="debian_xfce" class="max-size-img-post"&gt;&lt;/a&gt;
 &lt;figcaption&gt;Debian Xfce in its glorious simplicity.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="xfce-is-minimalist-enough-and-hassle-free"&gt;Xfce Is Minimalist Enough and Hassle-Free&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s also about the combination of &lt;strong&gt;Debian + Xfce&lt;/strong&gt;: while Debian makes sure the system remains functional as a whole, Xfce is the solution for interacting with applications and windows without glitches in a &amp;ldquo;&lt;em&gt;floating mode&lt;/em&gt;&amp;rdquo; where all windows can be grabbed and moved around easily. Debian itself keeps old packages around by choice and Xfce has a &lt;em&gt;very&lt;/em&gt; slow release cycle yet also provides stability out of the box. This means that installing Xfce on Debian &lt;strong&gt;has&lt;/strong&gt; to work because bugs have been evened out over &lt;strong&gt;years&lt;/strong&gt; of effort from both teams. This is an easy yet very satisfying solution.&lt;/p&gt;
&lt;h3 id="xfce-vs-kde"&gt;Xfce vs KDE&lt;/h3&gt;
&lt;p&gt;One of the main appeals of desktop environments like KDE and GNOME is that they have more features and add them more often. They do use more resources and even though they have gone through substantial optimizations over the years, they still feel less snappy on older systems compared to simpler window managers or even Xfce. Recently, KDE caught up with Xfce in terms of resources utilization, but there&amp;rsquo;s one major reason I just can&amp;rsquo;t rely on it on a production machine: in every single release I have tried (from KDE 2.x in the early 2000s to Plasma 5.x), I was confronted with numerous bugs within minutes of delving into it. I have always been faced with some minor troubles on GNOME too (versions 2 and 3), but it&amp;rsquo;s never been as severe as with KDE. KDE has plenty of cool ideas and is fully customizable, but that&amp;rsquo;s to a fault in my view.&lt;/p&gt;
&lt;h3 id="xfce-vs-gnome"&gt;Xfce vs GNOME&lt;/h3&gt;
&lt;p&gt;On the other hand, GNOME does consume at least twice as much RAM and CPU compared with Xfce even with no extensions enabled on GNOME and a couple of plugins activated on Xfce. I enjoy how GNOME deals with virtual desktops and think this can be a great productivity enhancement, but once I&amp;rsquo;ve configured Xfce to be mainly keyboard-driven, I prefer keeping it simpler with less transition effects and other nice visual additions. On the graphical side of things, GNOME with Wayland has never worked as well for me as with Xorg, so that&amp;rsquo;s something else to watch for.&lt;/p&gt;
&lt;h3 id="xfce-vs-i3"&gt;Xfce vs i3&lt;/h3&gt;
&lt;p&gt;Well, &lt;code&gt;i3&lt;/code&gt; is a different beast in its own right and has taken a special place in my heart. It uses less memory and CPU than any desktop environment out there and can be used with minimalistic software, like the &lt;code&gt;st&lt;/code&gt; terminal and the dynamic menu &lt;code&gt;dmenu&lt;/code&gt; (read the article about &lt;a href="https://www.sglavoie.com/posts/tip-the-scales-in-times-of-instability-with-the-rock-solid-debian/"&gt;suckless tools&lt;/a&gt; if that resonates with your style!). There are still a few things that I didn&amp;rsquo;t like very much about it, such as the way windows are managed in fullscreen mode, the default lack of a convenient master/slave tiling layout (similar to &lt;code&gt;dwm&lt;/code&gt; and &lt;code&gt;bspwm&lt;/code&gt;) and the way one interacts with external monitor(s), where workspaces use the same numbering across multiple screens. But i3 with Debian feels more mature and is (again) a bit older than what you might find elsewhere. There is &lt;a href="https://i3wm.org/docs/userguide.html#multi_monitor"&gt;a comprehensive section in the i3 User&amp;rsquo;s Guide&lt;/a&gt; that explains how to work around some issues.&lt;/p&gt;
&lt;p&gt;I find that maximizing windows works like what you would expect in Xfce, covering everything but the menu bar. There&amp;rsquo;s also the fact that Xfce makes it very convenient to add and remove virtual desktops on the fly instead of having a bunch of those at all time. With minimal Bash scripting, windows in Xfce can be moved around from one monitor to the other, replicating a useful feature available in i3. Xfce, having only &lt;em&gt;floating&lt;/em&gt; windows, behaves better with applications like VirtualBox and GIMP by default. And there&amp;rsquo;s also some common ground with the &amp;ldquo;pseudo tiling&amp;rdquo; available in Xfce which makes i3 much less unique, although i3 makes it a lot easier to maximize the screen estate being used.&lt;/p&gt;
&lt;figure&gt;
 &lt;a href="https://www.sglavoie.com/images/posts/0020_stable_system_debian/debian_i3.png"&gt;&lt;img src="https://www.sglavoie.com/images/posts/0020_stable_system_debian/debian_i3.png" alt="debian_i3" class="max-size-img-post"&gt;&lt;/a&gt;
 &lt;figcaption&gt;Debian i3 using up to the last available pixel.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;In the department of customization, i3 is very good, but having to edit a configuration file manually each time a little change is desired can become tiresome. Xfce has a wonderful settings manager which makes it easy to adjust many system settings as well as those related only to the window manager. i3 requires initially quite a bit more effort to work and will incur a few additional dependencies if one wants to make it look better. Xfce strikes a very good balance: it&amp;rsquo;s highly customizable; pretty much bug-free in my experience and is usable right away without any surprise. Once both are fully configured to match one&amp;rsquo;s need, I tend to rely on i3 to be more productive and keep Xfce as a functional backup if someone else is going to try to use the mouse on my system to accomplish any kind of useful action with the windows ;).&lt;/p&gt;
&lt;p&gt;I find that installing Debian with an Xfce base leads to having enough useful software pre-installed compared to a barebone installation and installing i3 afterwards only makes the transition easier.&lt;/p&gt;
&lt;h3 id="xfce-vs-other-window-managers"&gt;Xfce vs Other Window Managers&lt;/h3&gt;
&lt;p&gt;Now, there is an endless stream of other options to explore and I don&amp;rsquo;t know enough about many of those to dare to comment. But from those I tried, I can certainly say that I preferred the ease of use of Xfce over other more minimalistic approaches like Openbox, Enlightenment and Fluxbox. Xfce offers all you need out of the box, but not much more, which is what I&amp;rsquo;m looking for at this moment. On the other hand, making &lt;code&gt;dwm&lt;/code&gt; work in one precise way can be tricky and requires many tweaks before the configuration can remain untouched for a while. I do not like the necessity of recompiling the source code every single time a tiny change is made which led me to discard it as a convenient option in the long run. I like making small visual adjustments to my system from time to time and I want this to be as frictionless as possible.&lt;/p&gt;
&lt;p&gt;Otherwise, &lt;code&gt;dwm&lt;/code&gt; and &lt;code&gt;bspwm&lt;/code&gt; might be some very decent options if one is inclined to be tweaking everything from scratch (it&amp;rsquo;s not really a facultative step anyways!), but Xfce integrates everything one might need under very few different packages and has been extremely reliable for me from the beginning. On any kind of modern machine, the extra system resources used up by Xfce compared to those lighter alternatives really don&amp;rsquo;t mean much in the end because it is compensated with the presence of useful applets and tools which definitely make one&amp;rsquo;s life easier.&lt;/p&gt;
&lt;h2 id="its-ideal-for-developers"&gt;It&amp;rsquo;s Ideal for Developers&lt;/h2&gt;
&lt;h3 id="resources-efficiency--effectiveness"&gt;Resources Efficiency &amp;amp; Effectiveness&lt;/h3&gt;
&lt;p&gt;Debian with a light working environment is resource-efficient and comes with much less software out of the box compared to the KDE or GNOME editions: instead, more resources are available for hungry applications like heavy IDEs. Installing applications specific to those desktop environments work flawlessly too. Not only does Debian consume less resources (especially while running Xfce/i3 on top), it does so extremely well and offers great performance.&lt;/p&gt;
&lt;figure&gt;
 &lt;a href="https://www.sglavoie.com/images/posts/0020_stable_system_debian/resources_utilization.png"&gt;&lt;img src="https://www.sglavoie.com/images/posts/0020_stable_system_debian/resources_utilization.png" alt="resources_utilization" class="max-size-img-post"&gt;&lt;/a&gt;
 &lt;figcaption&gt;Debian Xfce mostly at rest.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="rock-solid-stability-again-big-selling-point"&gt;Rock-Solid Stability (Again, Big Selling Point!)&lt;/h3&gt;
&lt;p&gt;Since it&amp;rsquo;s so stable, any release of Debian is currently supported for at least 3 years and up to 5 years for LTS (Long Term Support) releases, which means one doesn&amp;rsquo;t have to worry about constantly upgrading the system. For a start, upgrading packages on the stable branch of Debian very rarely leads to a broken system, unlike on more bleeding edge distros like Fedora or Manjaro where downloading a few months old release almost guarantees some unexpected challenges.&lt;/p&gt;
&lt;h3 id="packages-availability"&gt;Packages Availability&lt;/h3&gt;
&lt;p&gt;With currently close to 58,000 packages offered on Debian, there&amp;rsquo;s a very good chance that anything one might need will be available. Working with up-to-date, proprietary applications like Google Chrome, Zoom or Slack is also pain-free: most companies, when they do consider Linux, opt for sharing a classic &lt;code&gt;deb&lt;/code&gt; package, the format used on Debian and Debian-based systems. Some of those packages can also be found or added directly to the sources managed by the package manager, allowing for easy, automatic updates.&lt;/p&gt;
&lt;figure&gt;
 &lt;a href="https://www.sglavoie.com/images/posts/0020_stable_system_debian/debian_packages.png"&gt;&lt;img src="https://www.sglavoie.com/images/posts/0020_stable_system_debian/debian_packages.png" alt="debian_packages" class="max-size-img-post"&gt;&lt;/a&gt;
 &lt;figcaption&gt;Synaptic, the legendary package manager.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="large-community-with-freedom-in-mind"&gt;Large Community with Freedom in Mind&lt;/h3&gt;
&lt;p&gt;Because no company backs Debian directly, it relies on a community effort to keep going and it has done so for a long time, having now hundreds of distributions being based on it. This means that it&amp;rsquo;s easy to find a ton of documentation and tutorials giving solutions taking into account Debian-based systems. One will be able to fix any issue cropping up thanks to the &lt;a href="http://forums.debian.net/"&gt;Debian User Forums&lt;/a&gt; and of course thanks to the immense popularity of Ubuntu, which contributes tremendously to making answers available in &lt;a href="https://ubuntuforums.org/"&gt;its forums&lt;/a&gt; and in the &lt;a href="https://askubuntu.com/"&gt;Stack Exchange&lt;/a&gt; network.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="resources-to-get-started"&gt;Resources to Get Started&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.debian.org/doc/"&gt;Debian Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://forums.debian.net/"&gt;Debian User Forums&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.debian.org/"&gt;Debian Wiki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Developer-oriented: &lt;a href="https://www.debian.org/doc/manuals/developers-reference/resources.html"&gt;resources for contributing to Debian&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Cloud-oriented: &lt;a href="https://www.digitalocean.com/community/tags/debian"&gt;tutorials for Debian on Digital Ocean&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://i3wm.org/"&gt;i3 tiling window manager&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.xfce.org/"&gt;Xfce Desktop Environment&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;After trying many different Linux distributions and desktop environments, I keep coming back to what satisfies me best in the end: stability and usability. Debian feels a bit old, but at the same time one knows it delivers on what it promises. The same can be said for Xfce and i3. This is also what makes them such a good combo: despite not being cutting edge in the realm of features, there&amp;rsquo;s no way it could break as easily as KDE or GNOME, particularly on less stable distributions. There are still a few rough edges when it comes to customizing both Xfce and i3 in my opinion, but when looking for something that just works and will keep doing so, Debian is hard to beat.&lt;/p&gt;</content:encoded><dc:creator>Sébastien Lavoie</dc:creator><pubDate>Sun, 05 Apr 2020 12:14:00 -0500</pubDate><guid isPermaLink="false">https://www.sglavoie.com/posts/tip-the-scales-in-times-of-instability-with-the-rock-solid-debian/</guid><category>tools</category><category>debian</category><category>i3</category><category>linux</category><category>stability</category><category>xfce</category></item><item><title>Ignoring Sync of Local Files to Dropbox on Linux</title><link>https://www.sglavoie.com/posts/ignoring-sync-of-local-files-to-dropbox-on-linux/</link><description>To make the most of Dropbox, it can make sense to backup the files you care the most about and skip the ones that simply take too long to upload and eat up all your space. Such candidates could be hidden .git/ folders and node_modules/, but how do you exclude them locally? Let’s find out.</description><content:encoded>&lt;hr&gt;
&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.dropbox.com"&gt;Dropbox&lt;/a&gt; is an awesome company which has been until recently the working home of none other than &lt;a href="https://gvanrossum.github.io"&gt;Guido van Rossum&lt;/a&gt;, the creator of the &lt;a href="https://www.python.org"&gt;Python&lt;/a&gt; programming language. It works like a charm out of the box on Linux and can be installed easily enough through the package manager that comes with your chosen distribution.&lt;/p&gt;
&lt;h2 id="why-dropbox"&gt;Why Dropbox?&lt;/h2&gt;
&lt;p&gt;In my experience, it has been working flawlessly and syncs consistently faster than Google Drive. It&amp;rsquo;s also worth mentioning that there is still no official Google Drive Linux client to this day: some users of the &lt;a href="https://www.gnome.org"&gt;GNOME&lt;/a&gt; desktop environment will connect to their Google account and mount Google Drive within the file manager &lt;a href="https://wiki.gnome.org/Apps/Files"&gt;Nautilus/Files&lt;/a&gt;; other users will use the paid software &lt;a href="https://www.insynchq.com"&gt;Insync&lt;/a&gt; or the free software alternative &lt;a href="https://liberodark.github.io/ODrive/"&gt;ODrive&lt;/a&gt;. No thanks.&lt;/p&gt;
&lt;p&gt;On the other hand, Dropbox is easy to use with any flavor of Linux and also syncs seamlessly with mobile devices. I use Dropbox for its convenience, but other solutions exist like &lt;a href="https://syncthing.net"&gt;Syncthing&lt;/a&gt; that do not depend on proprietary software and third-party cloud services. I store mostly insensitive information in my Dropbox account and for the few files that happen to be a bit more sensitive (such as the password database I synchronize on both desktop and mobile with &lt;a href="https://keepassxc.org"&gt;KeePassXC&lt;/a&gt; and &lt;a href="https://github.com/PhilippC/keepass2android"&gt;Keepass2Android&lt;/a&gt;, respectively), they are of course encrypted (hopefully in a secure way).&lt;/p&gt;
&lt;p&gt;Because I like to keep things simple and light on system resources, I do not let Dropbox run in the background (it only syncs once a day in the evening). Since all one needs to do in order to use it is to create and modify files inside a specific folder (such as &lt;code&gt;~/Dropbox&lt;/code&gt; by default), it can just synchronize at any moment and conflicts will be handled automatically if you make changes in more than one place that&amp;rsquo;s being synced.&lt;/p&gt;
&lt;h2 id="so-whats-wrong-with-dropbox"&gt;So, what&amp;rsquo;s wrong with Dropbox?&lt;/h2&gt;
&lt;p&gt;With all that said, there&amp;rsquo;s one little feature that I find missing with Dropbox when using the official Linux client and that&amp;rsquo;s the &lt;strong&gt;ability to selectively sync local files&lt;/strong&gt;. Yes, there is a &lt;a href="https://help.dropbox.com/installs-integrations/sync-uploads/selective-sync-overview"&gt;selective sync&lt;/a&gt; feature available, but that will delete the local copy of your files and store them in the cloud only, &lt;em&gt;not the other way around by keeping your local files intact and prevent uploading them to the cloud&lt;/em&gt;. There are some hacks you can do to avoid this, but this isn&amp;rsquo;t a particularly enticing work flow, because we can do better.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.sglavoie.com/images/posts/0019_ignoring-local-files-to-sync-with-dropbox-on-linux/dropbox_selective_sync.png"&gt;&lt;img src="https://www.sglavoie.com/images/posts/0019_ignoring-local-files-to-sync-with-dropbox-on-linux/dropbox_selective_sync.png" alt="dropbox_selective_sync" class="max-size-img-post"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You may have heard of other alternatives like &lt;a href="https://www.goodsync.com"&gt;GoodSync&lt;/a&gt; that allow, through yet another third-party proprietary software, to ignore specific files at your request. That&amp;rsquo;s not what we are after here: instead, there&amp;rsquo;s something you can do from the terminal that works quite well, too. At the time of this writing, it is still a &lt;em&gt;beta feature&lt;/em&gt; &lt;a href="https://help.dropbox.com/files-folders/restore-delete/ignored-files"&gt;according to this page&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
 &lt;p&gt;This feature is currently in beta and not available to all Dropbox users. It will be rolled out to more users in the future.&lt;/p&gt;

&lt;/blockquote&gt;&lt;p&gt;Yet, because you can work with this feature programmatically to ignore and &lt;em&gt;un-ignore&lt;/em&gt; files from your Dropbox directory, I thought it was worth giving it a try. Here is how I&amp;rsquo;m using it to give you a few ideas.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="any-simple-example"&gt;Any simple example?&lt;/h2&gt;
&lt;p&gt;Getting started is quick and painless. To ignore a file within your Dropbox folder, you only need to use the &lt;code&gt;attr&lt;/code&gt; (on Linux, else &lt;code&gt;xattr&lt;/code&gt; on macOS) command to &lt;strong&gt;set&lt;/strong&gt; (&lt;code&gt;-s&lt;/code&gt;) (or &lt;code&gt;-w&lt;/code&gt; &lt;strong&gt;write&lt;/strong&gt; on macOS) the special attribute &lt;code&gt;com.dropbox.ignored&lt;/code&gt; to give it a &lt;strong&gt;value&lt;/strong&gt; of &lt;code&gt;1&lt;/code&gt; (&lt;code&gt;-V 1&lt;/code&gt;) so it ignores a file (&lt;code&gt;file.txt&lt;/code&gt; in this example) as follow:&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/file/in/Dropbox/folder
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;attr -s com.dropbox.ignored -V &lt;span class="m"&gt;1&lt;/span&gt; file.txt &lt;span class="c1"&gt;# Linux&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;xattr -w com.dropbox.ignored &lt;span class="m"&gt;1&lt;/span&gt; file.txt &lt;span class="c1"&gt;# macOS&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="ignore-all-git-and-node_modules-folders"&gt;Ignore all .git and node_modules folders&lt;/h2&gt;
&lt;p&gt;Things get &lt;strong&gt;really&lt;/strong&gt; interesting when we can do that automatically by matching a specific pattern (it depends who you ask, anyways). How about exploring recursively the whole directory tree to exclude only hidden &lt;code&gt;.git&lt;/code&gt; folders? Suppose you store your Git projects in &lt;code&gt;~/Dropbox/git/&lt;/code&gt;. You would then do something like this:&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/Dropbox/git/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Linux&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -type d -name &lt;span class="s2"&gt;&amp;#34;.git&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; xargs -I &lt;span class="o"&gt;{}&lt;/span&gt; attr -s com.dropbox.ignored -V &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;{}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# macOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -type d -name &lt;span class="s2"&gt;&amp;#34;.git&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; xargs -I &lt;span class="o"&gt;{}&lt;/span&gt; xattr -w com.dropbox.ignored &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;{}&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In an instant, you will start getting some feedback printed to the terminal for each &lt;code&gt;.git&lt;/code&gt; folder that is being found:&lt;/p&gt;
&lt;div class="code-block code-block--wrap"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Attribute &amp;#34;com.dropbox.ignored&amp;#34; set to a 1 byte value for ./path/to/.git:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Dealing with &lt;code&gt;node_modules&lt;/code&gt; folders is equally easy. Because a message will be printed to the console every time a file attribute is changed, you could want to delete the output (preferably once you are sure you are modifying only the targeted files!) by redirecting it to &lt;code&gt;/dev/null&lt;/code&gt;, a &lt;em&gt;null device&lt;/em&gt; that discards all data it receives. We can always split a long command onto multiple lines with a backslash character &lt;code&gt;\&lt;/code&gt; like so (it&amp;rsquo;s not required right after the pipe &lt;code&gt;|&lt;/code&gt; symbol):&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -type d -name &lt;span class="s2"&gt;&amp;#34;node_modules&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; xargs -I &lt;span class="o"&gt;{}&lt;/span&gt; attr -s com.dropbox.ignored -V &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;{}&amp;#34;&lt;/span&gt; &amp;gt; /dev/null&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2 id="can-we-make-this-simpler"&gt;Can we make this simpler?&lt;/h2&gt;
&lt;p&gt;Yes we can! An &lt;code&gt;alias&lt;/code&gt; might be a bit hard to manage, but we can definitely create a set of functions that will be accessible from anywhere in the terminal. It suffices to add them to your shell configuration file, which could be located in &lt;code&gt;~/.profile&lt;/code&gt;, &lt;code&gt;~/.bash_profile&lt;/code&gt;, &lt;code&gt;~/.zshrc&lt;/code&gt; or something else depending on your shell.&lt;/p&gt;
&lt;p&gt;One solution that I see fit for this purpose is to have two distinct functions that have antagonistic effects so that we can revert our changes in a pinch. Basically, setting a value of &lt;code&gt;1&lt;/code&gt; for the attribute &lt;code&gt;com.dropbox.ignored&lt;/code&gt; ignores a file while setting it back to &lt;code&gt;0&lt;/code&gt; tells Dropbox to sync it again. Our functions could be conveniently called &lt;code&gt;dropbox-ignore&lt;/code&gt; and &lt;code&gt;dropbox-sync&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, the following functions could become quite a bit more complicated to take into account various scenarios and custom behaviors, but let&amp;rsquo;s keep things simple and assume that the user knows what is going to happen. We could have our two functions as follow:&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Ignore specific files/directories in Dropbox&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dropbox-ignore&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;arg1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;arg2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -z &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$arg1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -z &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$arg2&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Usage: dropbox-ignore &amp;lt;f|d&amp;gt; &amp;lt;name&amp;gt; (e.g. dropbox-ignore d .git)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; find ~/Dropbox -type &lt;span class="nv"&gt;$arg1&lt;/span&gt; -name &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$arg2&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; xargs -I &lt;span class="o"&gt;{}&lt;/span&gt; xattr -w com.dropbox.ignored &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;{}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Sync specific files/directories in Dropbox&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# that were previously ignored (or not)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dropbox-sync&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;arg1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;arg2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -z &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$arg1&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -z &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$arg2&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Usage: dropbox-sync &amp;lt;f|d&amp;gt; &amp;lt;name&amp;gt; (e.g. dropbox-sync d .git)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; find ~/Dropbox -type &lt;span class="nv"&gt;$arg1&lt;/span&gt; -name &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$arg2&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; xargs -I &lt;span class="o"&gt;{}&lt;/span&gt; xattr -d com.dropbox.ignored &lt;span class="s2"&gt;&amp;#34;{}&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="how-do-you-use-those-functions"&gt;How do you use those functions?&lt;/h2&gt;
&lt;p&gt;Our commands will be accessible by typing &lt;code&gt;dropbox-ignore&lt;/code&gt; and &lt;code&gt;dropbox-sync&lt;/code&gt; the next time we open a terminal window. Both functions do exactly the same thing, but &lt;code&gt;dropbox-ignore&lt;/code&gt; sets the attribute value to &lt;code&gt;1&lt;/code&gt; to ignore files and &lt;code&gt;dropbox-sync&lt;/code&gt; sets the attribute to &lt;code&gt;0&lt;/code&gt; to allow syncing to happen.&lt;/p&gt;
&lt;p&gt;&lt;sub&gt;Note: For simplicity and practicality, keep in mind that those commands will search &lt;strong&gt;recursively from the specified directory&lt;/strong&gt;. It&amp;rsquo;s also good to know that if you set an attribute value to &lt;code&gt;1&lt;/code&gt; then back to &lt;code&gt;0&lt;/code&gt; again, Dropbox will need to re-sync the affected files and directories.&lt;/sub&gt;&lt;/p&gt;
&lt;p&gt;We need to pass them two arguments: the first is the type of search to perform (pass &lt;code&gt;f&lt;/code&gt; for &lt;strong&gt;files&lt;/strong&gt; and &lt;code&gt;d&lt;/code&gt; for &lt;strong&gt;directories&lt;/strong&gt;) and the second is the pattern to match in the name (&lt;code&gt;node_modules&lt;/code&gt; or &lt;code&gt;.git&lt;/code&gt; would fit here, no need to use quotes). Concretely, that will look like this:&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# To ignore a file matching the pattern `myfile`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dropbox-ignore f myfile
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# To avoid syncing node_modules/ directory&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dropbox-ignore d node_modules
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Te re-add a .git/ folder to Dropbox&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dropbox-sync d .git&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This tip may certainly not be the best approach to solving this particular issue with Dropbox on Unix, but I hope you find it useful nevertheless as it worked out very nicely on my end! One could store files and directories elsewhere, working with symbolic links or hard links as necessary to reference files or simply give up on making a backup with Dropbox in some circumstances. But I like to keep an extra copy of projects I&amp;rsquo;m working on in Dropbox and that can include potentially large files that don&amp;rsquo;t need to be backed up, so ignoring what&amp;rsquo;s not indispensable can speed up the syncing process tremendously while keeping disk usage in the cloud possibly much lower.&lt;/p&gt;
&lt;p&gt;Dropbox only calculates the size of the files being synced in the cloud, so you can end up needing a lot more space locally if you ignore a number of big files or, conversely, selectively syncing many files will result in a cloud storage larger than what&amp;rsquo;s needed locally.&lt;/p&gt;</content:encoded><dc:creator>Sébastien Lavoie</dc:creator><pubDate>Sat, 30 Nov 2019 13:22:00 -0600</pubDate><guid isPermaLink="false">https://www.sglavoie.com/posts/ignoring-sync-of-local-files-to-dropbox-on-linux/</guid><category>tips-and-tricks</category><category>aliases</category><category>macos</category><category>linux</category><category>shell</category><category>terminal</category></item><item><title>Using dmenu to Optimize Common Tasks</title><link>https://www.sglavoie.com/posts/using-dmenu-to-optimize-common-tasks/</link><description>If remembering dozens of keyboard shortcuts isn’t your forte, let dmenu come to the rescue! With this awesome tool, you will be able to create menus from plain text files swiftly and effortlessly (almost).</description><content:encoded>&lt;hr&gt;
&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://tools.suckless.org/dmenu"&gt;dmenu&lt;/a&gt; is one of those tools that look a little unimpressive at first but can accomplish so much! It&amp;rsquo;s a program that you can use to receive any output redirected from other programs (through pipes in the terminal, the symbol &lt;code&gt;|&lt;/code&gt;) and treat that output so that it can pop up within a simple menu to make it available for execution. If you want to know more about other fantastic tools from &lt;a href="https://suckless.org"&gt;suckless.org&lt;/a&gt;, I &lt;a href="https://www.sglavoie.com/posts/using-dmenu-to-optimize-common-tasks/"&gt;went over some of them before&lt;/a&gt;, such as the &lt;code&gt;st&lt;/code&gt; terminal and &lt;code&gt;slock&lt;/code&gt;, a dead simple screen locker.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="any-simple-example"&gt;Any Simple Example?&lt;/h2&gt;
&lt;p&gt;You bet! Before diving in with how to install it and some more concrete examples, you could give &lt;code&gt;dmenu&lt;/code&gt; a go with a simple command such as the following (assuming the program is installed on your machine).&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ls &lt;span class="p"&gt;|&lt;/span&gt; dmenu&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This will effectively &amp;ldquo;pipe&amp;rdquo; the output of &lt;code&gt;ls&lt;/code&gt; into &lt;code&gt;dmenu&lt;/code&gt; and a menu like the following would appear (by default, it shows as a thin stripe at the top covering the width of the screen):&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.sglavoie.com/images/posts/0018_using-dmenu-to-optimize-common-tasks/dmenu_ls_command.png"&gt;&lt;img src="https://www.sglavoie.com/images/posts/0018_using-dmenu-to-optimize-common-tasks/dmenu_ls_command.png" alt="dmenu_ls_command" class="max-size-img-post"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you start typing, the displayed list will be filtered down like so:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.sglavoie.com/images/posts/0018_using-dmenu-to-optimize-common-tasks/dmenu_ls_command_typing.png"&gt;&lt;img src="https://www.sglavoie.com/images/posts/0018_using-dmenu-to-optimize-common-tasks/dmenu_ls_command_typing.png" alt="dmenu_ls_command_typing" class="max-size-img-post"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can also switch to the next item to be highlighted by typing &lt;code&gt;Ctrl + n&lt;/code&gt;, to the previous item by typing &lt;code&gt;Ctrl + p&lt;/code&gt; and exit by reaching for the &lt;code&gt;Escape&lt;/code&gt; key. For now, if you type &lt;code&gt;Enter&lt;/code&gt; once your desired selection is highlighted, the selection will be outputted to the terminal and that will be the end of it. Let&amp;rsquo;s convert this into a practical thing, then.&lt;/p&gt;
&lt;p&gt;Keeping the same output as before which only contained directories, we could open a file manager (here, I&amp;rsquo;m going with &lt;code&gt;pcmanfm&lt;/code&gt;) and do something like this (bear with me, the explanation follows!):&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ls &lt;span class="p"&gt;|&lt;/span&gt; dmenu -l &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; xargs -I &lt;span class="o"&gt;{}&lt;/span&gt; pcmanfm &lt;span class="s2"&gt;&amp;#34;{}&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This is now a fully functional example, albeit its practicality is debatable. What will happen, exactly?&lt;/p&gt;
&lt;p&gt;First, &lt;code&gt;ls&lt;/code&gt; will output a list of directories in the current working directory. That is, the following would be printed in the terminal without any piping:&lt;/p&gt;
&lt;div class="code-block code-block--wrap"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Desktop Downloads Learning Pictures Public Templates virtualbox_vms
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Documents Dropbox Music Programming SortOut Videos&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When we &lt;em&gt;pipe&lt;/em&gt; this into &lt;code&gt;dmenu&lt;/code&gt;, we will get a menu with all that output nicely formatted vertically, which is what the &lt;code&gt;-l 5&lt;/code&gt; options does (here, we want only &lt;strong&gt;5&lt;/strong&gt; lines to show). We will see a maximum of &lt;strong&gt;5&lt;/strong&gt; items as this is the value we passed to the &lt;code&gt;-l&lt;/code&gt; option:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.sglavoie.com/images/posts/0018_using-dmenu-to-optimize-common-tasks/dmenu_ls_command_vertical_5_items.png"&gt;&lt;img src="https://www.sglavoie.com/images/posts/0018_using-dmenu-to-optimize-common-tasks/dmenu_ls_command_vertical_5_items.png" alt="dmenu_ls_command_vertical_5_items" class="max-size-img-post"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We can still start typing a word that doesn&amp;rsquo;t show up in this list like &lt;code&gt;Mu&lt;/code&gt; and we will see that this list is filtered to only include the matching directory &lt;code&gt;Music&lt;/code&gt; even though we couldn&amp;rsquo;t see it before since we limited our results to &lt;strong&gt;5&lt;/strong&gt; items. We could also use the same technique with &lt;code&gt;Ctrl + n&lt;/code&gt; and &lt;code&gt;Ctrl + p&lt;/code&gt; to cycle between the elements.&lt;/p&gt;
&lt;p&gt;Up to this point, we are getting our selection outputted to the terminal. Next, we pipe it into &lt;code&gt;xargs&lt;/code&gt;, which will allow us to specify a command to which we will pass our result (what is printed to the terminal) as an argument (we could make use of more arguments depending on the output we get, but let&amp;rsquo;s start simple). The &lt;code&gt;-I {}&lt;/code&gt; option will make it possible to &amp;ldquo;quote&amp;rdquo; our result so it is read as a single argument and properly &lt;em&gt;escaped&lt;/em&gt;. This means that without this option, if we have spaces or other special characters in the argument (such as a folder called &lt;code&gt;My Music&lt;/code&gt;), it would try to pass each word as a new argument to &lt;code&gt;pcmanfm&lt;/code&gt;, trying to open both &lt;code&gt;My&lt;/code&gt; and &lt;code&gt;Music&lt;/code&gt; directories at once.&lt;/p&gt;
&lt;p&gt;We are representing our output as &lt;code&gt;{}&lt;/code&gt; and when we quote it with &lt;code&gt;pcmanfm &amp;quot;{}&amp;quot;&lt;/code&gt;, spaces are interpreted without any trouble. If we wanted to use various arguments instead, we could try something like this:&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;file1.txt file2.txt\nfile3.txt file4.txt&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; dmenu -l &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; xargs cat&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The part before the first pipe character will print to the terminal those two lines:&lt;/p&gt;
&lt;div class="code-block code-block--wrap"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;file1.txt file2.txt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;file3.txt file4.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When we pipe this into &lt;code&gt;dmenu -l 2&lt;/code&gt;, we will get this menu:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.sglavoie.com/images/posts/0018_using-dmenu-to-optimize-common-tasks/dmenu_echo_command_filenames.png"&gt;&lt;img src="https://www.sglavoie.com/images/posts/0018_using-dmenu-to-optimize-common-tasks/dmenu_echo_command_filenames.png" alt="dmenu_echo_command_filenames" class="max-size-img-post"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Typing &lt;code&gt;Enter&lt;/code&gt; on one of the highlighted items would then trigger &lt;code&gt;xargs&lt;/code&gt; to pass the content literally to &lt;code&gt;cat&lt;/code&gt; as arguments, which would then print to the terminal the content of both &lt;code&gt;file1.txt&lt;/code&gt; and &lt;code&gt;file2.txt&lt;/code&gt; (the first line containing two arguments for &lt;code&gt;cat&lt;/code&gt;) or the content of both &lt;code&gt;file3.txt&lt;/code&gt; and &lt;code&gt;file4.txt&lt;/code&gt; (the second line also containing two arguments for &lt;code&gt;cat&lt;/code&gt;) in succession.&lt;/p&gt;
&lt;p&gt;Now that we got our feet wet with what &lt;code&gt;dmenu&lt;/code&gt; does (&lt;em&gt;displays a menu&lt;/em&gt;), we might want to install it.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="how-do-you-install-it"&gt;How do You Install It?&lt;/h2&gt;
&lt;p&gt;In Manjaro Linux, it comes with &lt;code&gt;i3&lt;/code&gt; if you use that flavor of the distribution and can be opened by pressing the modifier key (either &lt;code&gt;Super/Windows&lt;/code&gt; key or &lt;code&gt;Alt&lt;/code&gt; key) along with the letter &lt;code&gt;d&lt;/code&gt;, as in the shortcut &lt;code&gt;mod + d&lt;/code&gt;, or by typing &lt;code&gt;dmenu_run&lt;/code&gt; in a terminal, which will present a list of installed applications to launch. Otherwise:&lt;/p&gt;
&lt;h2 id="debian-based-such-as-ubuntu"&gt;Debian-based (such as Ubuntu)&lt;/h2&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install dmenu&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="arch-based-such-as-manjaro"&gt;Arch-based (such as Manjaro)&lt;/h2&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pacman -Syu dmenu&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;You can also install it from your distribution&amp;rsquo;s package manager if available or &lt;a href="https://tools.suckless.org/dmenu"&gt;from source&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="useful-real-world-examples"&gt;Useful Real-World Examples&lt;/h2&gt;
&lt;p&gt;Here are a couple of ways I like to use &lt;code&gt;dmenu&lt;/code&gt; to open a menu with a list of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cheat sheets;&lt;/li&gt;
&lt;li&gt;filesystem paths;&lt;/li&gt;
&lt;li&gt;most used documents;&lt;/li&gt;
&lt;li&gt;documents &amp;amp; books I read at the university;&lt;/li&gt;
&lt;li&gt;custom scripts I want to run in the background.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here are a few screenshots of how it currently looks like in my daily usage so you get a better idea.&lt;/p&gt;
&lt;h2 id="cheat-sheets"&gt;Cheat sheets&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.sglavoie.com/images/posts/0018_using-dmenu-to-optimize-common-tasks/dmenu_cheat_sheets.png"&gt;&lt;img src="https://www.sglavoie.com/images/posts/0018_using-dmenu-to-optimize-common-tasks/dmenu_cheat_sheets.png" alt="dmenu_cheat_sheets" class="max-size-img-post"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="university-shortcuts"&gt;University shortcuts&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.sglavoie.com/images/posts/0018_using-dmenu-to-optimize-common-tasks/dmenu_university_shortcuts.png"&gt;&lt;img src="https://www.sglavoie.com/images/posts/0018_using-dmenu-to-optimize-common-tasks/dmenu_university_shortcuts.png" alt="dmenu_university_shortcuts" class="max-size-img-post"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="file-manager-shortcuts"&gt;File manager shortcuts&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.sglavoie.com/images/posts/0018_using-dmenu-to-optimize-common-tasks/dmenu_file_manager_shortcuts.png"&gt;&lt;img src="https://www.sglavoie.com/images/posts/0018_using-dmenu-to-optimize-common-tasks/dmenu_file_manager_shortcuts.png" alt="dmenu_file_manager_shortcuts" class="max-size-img-post"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So, how does that all work? As a starting point, all of those menus are launched through a specific keyboard shortcut that uses a mnemonic for each one (&lt;code&gt;mod&lt;/code&gt; being the &amp;ldquo;modifier&amp;rdquo; key on &lt;strong&gt;i3&lt;/strong&gt;, which is set to &lt;code&gt;Super/Windows&lt;/code&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;mod + Alt + c&lt;/code&gt;: &lt;strong&gt;c&lt;/strong&gt;heat sheets;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mod + Alt + d&lt;/code&gt;: &lt;strong&gt;d&lt;/strong&gt;ocuments;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mod + Alt + f&lt;/code&gt;: &lt;strong&gt;f&lt;/strong&gt;ile manager;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mod + Alt + s&lt;/code&gt;: &lt;strong&gt;s&lt;/strong&gt;cripts;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mod + Alt + u&lt;/code&gt;: &lt;strong&gt;u&lt;/strong&gt;niversity.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;rsquo;s take the cheat sheets example, which is a bit more interesting since it launches different applications.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="setting-up-a-custom-command"&gt;Setting Up a Custom Command&lt;/h2&gt;
&lt;h3 id="configuration-for-i3-bind-a-keyboard-shortcut"&gt;Configuration for i3 (bind a keyboard shortcut)&lt;/h3&gt;
&lt;p&gt;Here, I&amp;rsquo;m using &lt;a href="https://i3wm.org"&gt;i3&lt;/a&gt; to set a keyboard shortcut to run a specific command, but this will be a similar experience on other window managers and desktop environments.&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# i3config file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# The backslash at the end of the line allows us&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# to split the line to increase readability&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## Cheatsheets&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bindsym &lt;span class="nv"&gt;$mod&lt;/span&gt;+Mod1+c &lt;span class="nb"&gt;exec&lt;/span&gt; --no-startup-id &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat path/to/cheatsheets.conf &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; dmenu -l &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sed &lt;span class="s1"&gt;&amp;#39;s/.* \+//&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;You would usually be able to launch a custom command from your environment through a keyboard shortcut. If passing a direct command such as the above one isn&amp;rsquo;t an option, you can always store it in a Bash script and run that Bash script instead as the designated custom command. The script would then contain the following:&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## Cheatsheets&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat path/to/cheatsheets.conf &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; dmenu -l &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sed &lt;span class="s1"&gt;&amp;#39;s/.* \+//&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;As far as &lt;strong&gt;i3&lt;/strong&gt; is concerned, that&amp;rsquo;s all you need to do. You would need to reload the configuration file (by default: &lt;em&gt;i3config&lt;/em&gt;) where the previous &lt;code&gt;bindsym&lt;/code&gt; command has been set up to apply the changes (default shortcut to reload: &lt;code&gt;mod + Shift + c&lt;/code&gt;).&lt;/p&gt;
&lt;h3 id="configuration-for-cheatsheetsconf"&gt;Configuration for cheatsheets.conf&lt;/h3&gt;
&lt;p&gt;The content of this file is literally what will be shown when &lt;strong&gt;dmenu&lt;/strong&gt; opens it. An excerpt:&lt;/p&gt;
&lt;div class="code-block code-block--wrap"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#---------- Cheat Sheets -------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bash st -e nvim path/to/bash.sh
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git zathura path/to/github.pdf
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;vimwiki firefox path/to/vimwiki.html&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Here, we have set a maximum of &lt;strong&gt;30&lt;/strong&gt; lines to be displayed (&lt;code&gt;-l 30&lt;/code&gt;). What follows after an element has been selected with &lt;strong&gt;dmenu&lt;/strong&gt; allows us to parse the content of the line and retrieve only the command we are interested in with &lt;code&gt;sed&lt;/code&gt; before passing that filtered content around to &lt;code&gt;sh&lt;/code&gt; to execute it as a shell command. With more complex commands requiring multiples arguments to be received, we could add one more pipe between &lt;code&gt;sed&lt;/code&gt; and &lt;code&gt;sh&lt;/code&gt; like this (or with &lt;code&gt;xargs -I {}&lt;/code&gt; to avoid problems with spaces):&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat path/to/cheatsheets.conf &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; dmenu -l &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sed &lt;span class="s1"&gt;&amp;#39;s/.* \+//&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; xargs -r &lt;span class="p"&gt;|&lt;/span&gt; sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If the line we want to run only includes a path to a file as in:&lt;/p&gt;
&lt;div class="code-block code-block--wrap"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;myshortcut path/to/file.pdf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We could instead pipe it into an external command of choice if the same program applies to all items presented in the menu, say Firefox:&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat path/to/file.conf &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; dmenu -l &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sed &lt;span class="s1"&gt;&amp;#39;s/.* \+//&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; xargs -I &lt;span class="o"&gt;{}&lt;/span&gt; firefox &lt;span class="s2"&gt;&amp;#34;{}&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;What&amp;rsquo;s nice with the way pipes work in a Unix-like system is that we can chain harmless commands until the very end so they will simply be printed to the terminal. In this example, if we want to see how to filter our lines before running a command, we can do so as follow.&lt;/p&gt;
&lt;h4 id="pipe-1"&gt;Pipe 1&lt;/h4&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat path/to/cheatsheets.conf &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; dmenu -l &lt;span class="m"&gt;30&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If you remember from the menu we saw earlier, there&amp;rsquo;s a shortcut to open a cheat sheet for Git. Let&amp;rsquo;s say we selected that one with &lt;strong&gt;dmenu&lt;/strong&gt;. Because our command isn&amp;rsquo;t doing anything with the result, it will be outputted to the terminal like so (just like in the excerpt of &lt;code&gt;cheatsheets.conf&lt;/code&gt;):&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git zathura path/to/github.pdf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;What &lt;code&gt;sed&lt;/code&gt; does here is to cut everything from the beginning of the line up to where the command starts (that&amp;rsquo;s where we find &lt;a href="https://pwmt.org/projects/zathura/"&gt;zathura&lt;/a&gt;, which is a powerful document viewer), because we need to isolate that part of the line so it looks like a shell command we could run on its own. Let&amp;rsquo;s add a new pipe to our command and see what &lt;code&gt;sed&lt;/code&gt; does with it*.&lt;/p&gt;
&lt;p&gt;* &lt;sub&gt;We could have used other tools to parse the string like &lt;code&gt;awk&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;cut&lt;/code&gt;, etc.&lt;/sub&gt;&lt;/p&gt;
&lt;h4 id="pipe-2"&gt;Pipe 2&lt;/h4&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat path/to/cheatsheets.conf &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; dmenu -l &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sed &lt;span class="s1"&gt;&amp;#39;s/.* \+//&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If we select the same item as before with &lt;strong&gt;dmenu&lt;/strong&gt; to illustrate more clearly what this new addition does, we will get this output:&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;zathura path/to/github.pdf&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If we were to type this in the terminal (assuming the file exists and &lt;strong&gt;zathura&lt;/strong&gt; is installed!), that would do the trick and it would open with the specified document viewer. &lt;strong&gt;Pipe 2&lt;/strong&gt; and subsequent pipes before we execute something is where the filtering magic happen. In short:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Everything &lt;strong&gt;before&lt;/strong&gt; &lt;code&gt;| dmenu&lt;/code&gt; is how our input will look like when we run &lt;code&gt;dmenu&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Everything &lt;strong&gt;after&lt;/strong&gt; &lt;code&gt;| dmenu [options here] |&lt;/code&gt; is what we need to do to our input so that it is converted into a working shell command;&lt;/li&gt;
&lt;li&gt;Finally, what comes &lt;strong&gt;after the last pipe&lt;/strong&gt; (either &lt;code&gt;xargs&lt;/code&gt;, &lt;code&gt;sh&lt;/code&gt; or a combination of both) is our way to redirect our string to the shell so it can be executed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once we are visually satisfied with how our command is supposed to look like (it has to be something that works when typed directly in the terminal), the next step is to pipe it again so it can be executed.&lt;/p&gt;
&lt;h4 id="pipe-3"&gt;Pipe 3&lt;/h4&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat path/to/cheatsheets.conf &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;|&lt;/span&gt; dmenu -l &lt;span class="m"&gt;30&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sed &lt;span class="s1"&gt;&amp;#39;s/.* \+//&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;There we go, the command is launched. If we keep the same simple syntax in all of our &lt;code&gt;.conf&lt;/code&gt; files —or whatever extension we choose— where the content of our menus is stored in plain text, we can quickly and painlessly create keyboard shortcuts to run custom lists of commands that can be edited on the fly. Once our shortcuts are active, it&amp;rsquo;s only a matter of editing one of those &lt;code&gt;.conf&lt;/code&gt; files and automatically our lists will be up-to-date when we trigger the shortcut again.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="running-a-custom-script"&gt;Running a Custom Script&lt;/h2&gt;
&lt;p&gt;If we want to run custom scripts, we need to indicate a command that would work in the terminal, such as &lt;code&gt;python myscrypt.py&lt;/code&gt; or &lt;code&gt;./myscript.sh&lt;/code&gt;. When it comes to shell scripts, we have to make sure they are executable. We can do so through a file manager or within the terminal like this:&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chmod +x path/to/script.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This will add the necessary permissions for the user to execute the script. As we already know, we would then need to add a keyboard shortcut to launch our custom menu and store our command in a file like &lt;code&gt;scripts.conf&lt;/code&gt; that would contain the following:&lt;/p&gt;
&lt;div class="code-block code-block--wrap"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#---------- scripts.conf -------------------------------------------------------
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;myscript script.sh&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And that&amp;rsquo;s all there is to know to get piping with &lt;code&gt;dmenu&lt;/code&gt;! You may also find &lt;a href="https://www.youtube.com/watch?v=8E8sUNHdzG8"&gt;this video from Luke Smith&lt;/a&gt; on YouTube to be quite helpful as well, which is where the inspiration for this post came from. He also &lt;a href="https://www.youtube.com/watch?v=R9m723tAurA"&gt;posted a complementary video&lt;/a&gt; about adding prompts to your commands which is a nice way to add interactivity to your scripts!&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="chaining-dmenu-prompts"&gt;Chaining dmenu prompts&lt;/h2&gt;
&lt;p&gt;Another useful scenario is when you want to take a specific action based on the output of a previous command. For instance, let&amp;rsquo;s say you want to read a book but when you choose a &lt;code&gt;pdf&lt;/code&gt; with &lt;code&gt;dmenu&lt;/code&gt;, you want to be prompted for which reader to use while you want to let the system choose the default application for other types of files (e.g. &lt;code&gt;epub&lt;/code&gt; or &lt;code&gt;mobi&lt;/code&gt;). This could be achieved with a script similar to the following one:&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;find ~/Documents/calibre_library -type f -iname &lt;span class="s2"&gt;&amp;#34;*.pdf&amp;#34;&lt;/span&gt; -o &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -iname &lt;span class="s2"&gt;&amp;#34;*.epub&amp;#34;&lt;/span&gt; -o -iname &lt;span class="s2"&gt;&amp;#34;*.mobi&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; dmenu -l 30&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; *.pdf &lt;span class="o"&gt;]]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;READER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; -e &lt;span class="s2"&gt;&amp;#34;zathura\natril&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; dmenu -i -p &lt;span class="s2"&gt;&amp;#34;Which reader?&amp;#34;&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;$READER&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; xdg-open &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$FILE&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Here&amp;rsquo;s what&amp;rsquo;s happening:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;We &lt;code&gt;find&lt;/code&gt; all the files (&lt;code&gt;-type f&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;in the directory &lt;code&gt;~/Documents/calibre_library&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;that match a pattern that&amp;rsquo;s case-insensitive with &lt;code&gt;-iname&lt;/code&gt; (here, ending in either &lt;code&gt;pdf&lt;/code&gt;, &lt;code&gt;mobi&lt;/code&gt; or &lt;code&gt;epub&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;matching one file at a time (&lt;code&gt;-o&lt;/code&gt; can be interpreted to mean &amp;ldquo;only&amp;rdquo; and will keep searching if the previous file extension was not matched)&lt;/li&gt;
&lt;li&gt;then presenting 30 lines (&lt;code&gt;-l 30&lt;/code&gt;) of results at a time with &lt;code&gt;dmenu&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;then, if the file is a PDF, prompts whether to use &lt;code&gt;atril&lt;/code&gt; or &lt;code&gt;zathura&lt;/code&gt; as the file reader and open with the chosen program&lt;/li&gt;
&lt;li&gt;otherwise, open the file with the default application.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="customize-the-look-of-dmenu"&gt;Customize the Look of dmenu&lt;/h2&gt;
&lt;p&gt;As they say, &lt;em&gt;&amp;ldquo;beauty is in the eye of the beholder&amp;rdquo;&lt;/em&gt;. If you would rather make some changes to how dmenu look, you can. &lt;strong&gt;dmenu&lt;/strong&gt; will be searching for the configuration file located at &lt;code&gt;~/.dmenurc&lt;/code&gt;, which could contain something as put below (with this configuration, it will look like the screenshots shown previously):&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ~/.dmenurc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# define the font for dmenu to be used&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;DMENU_FN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;NotoSans-10.5&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# background colour for unselected menu-items&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;DMENU_NB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;#161925&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# textcolour for unselected menu-items&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;DMENU_NF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;#fdfffc&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# background colour for selected menu-items&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;DMENU_SB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;#235789&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# textcolour for selected menu-items&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;DMENU_SF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;#fdfffc&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# command for the terminal application to be used:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;TERMINAL_CMD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;st -e&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# export our variables&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;DMENU_OPTIONS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-fn &lt;/span&gt;&lt;span class="nv"&gt;$DMENU_FN&lt;/span&gt;&lt;span class="s2"&gt; -nb &lt;/span&gt;&lt;span class="nv"&gt;$DMENU_NB&lt;/span&gt;&lt;span class="s2"&gt; -nf &lt;/span&gt;&lt;span class="nv"&gt;$DMENU_NF&lt;/span&gt;&lt;span class="s2"&gt; -sf &lt;/span&gt;&lt;span class="nv"&gt;$DMENU_SF&lt;/span&gt;&lt;span class="s2"&gt; -sb &lt;/span&gt;&lt;span class="nv"&gt;$DMENU_SB&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Hopefully this introduction to what &lt;strong&gt;dmenu&lt;/strong&gt; has to offer gave you some ideas. I hope you&amp;rsquo;ll find many ways to adapt the examples so you can benefit from this amazing tool. You can find more configuration details in my &lt;a href="https://github.com/sglavoie/dotfiles/"&gt;dotfiles on GitHub&lt;/a&gt; for anything related to &lt;strong&gt;i3&lt;/strong&gt;, &lt;strong&gt;dmenu&lt;/strong&gt;, &lt;strong&gt;zathura&lt;/strong&gt;, &lt;strong&gt;st&lt;/strong&gt;, &lt;strong&gt;slock&lt;/strong&gt; and many more useful programs.&lt;/p&gt;
&lt;p&gt;Have a good time automating your digital life!&lt;/p&gt;</content:encoded><dc:creator>Sébastien Lavoie</dc:creator><pubDate>Sun, 10 Nov 2019 09:02:00 -0600</pubDate><guid isPermaLink="false">https://www.sglavoie.com/posts/using-dmenu-to-optimize-common-tasks/</guid><category>tips-and-tricks</category><category>bash</category><category>dmenu</category><category>i3</category><category>linux</category><category>productivity</category><category>script</category></item><item><title>Using i3 as a Window Manager for Increased Productivity</title><link>https://www.sglavoie.com/posts/using-i3-as-a-window-manager-for-increased-productivity/</link><description>I was striving to improve my productivity as one of my New Year’s resolutions and finally found the courage to take the time to try out i3, a fantastic window manager.</description><content:encoded>&lt;hr&gt;
&lt;h2 id="what-is-i3"&gt;What is i3?&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://i3wm.org/"&gt;i3&lt;/a&gt; is a tiling window manager. To get to know &lt;code&gt;i3&lt;/code&gt;
better, it&amp;rsquo;s good to situate what desktop environments are in the first
place.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="what-are-desktop-environments"&gt;What are desktop environments?&lt;/h3&gt;
&lt;p&gt;If you are familiar with Linux,
you certainly know about desktop environments such as
&lt;a href="https://www.gnome.org/"&gt;GNOME&lt;/a&gt;, &lt;a href="https://www.kde.org/"&gt;KDE&lt;/a&gt;,
&lt;a href="https://www.xfce.org/"&gt;Xfce&lt;/a&gt;&amp;hellip; and actually many
more are available (you can see &lt;a href="https://en.wikipedia.org/wiki/Desktop_environment"&gt;this article on
Wikipedia&lt;/a&gt;
for an extended selection)! The classic Graphical User Interface
(GUI) on Windows XP was known as
&lt;a href="https://en.wikipedia.org/wiki/Luna_%28theme%29"&gt;Luna&lt;/a&gt; and is now
called Modern on Windows 10.
&lt;a href="https://en.wikipedia.org/wiki/Aqua_%28user_interface%29"&gt;Aqua&lt;/a&gt; is the
name of the GUI on macOS. Well, every desktop environment comes with
a window manager, the main component that makes interactions with
windows possible, like moving, resizing, minimizing or closing them.&lt;/p&gt;
&lt;p&gt;Desktop environments are very useful in many ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They are usually very easy to set up as they come fully functional out
of the box. Like opening a user session on macOS or Windows.&lt;/li&gt;
&lt;li&gt;They are sometimes quite customizable, but you don&amp;rsquo;t have to change
anything to get them to work, as they normally set default applications
to open with certain file types.&lt;/li&gt;
&lt;li&gt;They automatically integrate services such as WiFi network detection,
automatic mounting of drives when you plug them in, etc.&lt;/li&gt;
&lt;li&gt;You can enable &lt;a href="https://en.wikipedia.org/wiki/Virtual_desktop"&gt;virtual
desktops&lt;/a&gt;
to split your work
across different spaces. This concept can grow to
&lt;em&gt;[Activities](&lt;a href="https://docs.kde.org/trunk5/en/kde-workspace/plasma-deskto"&gt;https://docs.kde.org/trunk5/en/kde-workspace/plasma-deskto&lt;/a&gt;
p/activities-interface.html)&lt;/em&gt;, which is a feature implemented in KDE
that allows you to use virtual spaces literally for different activities
by having settings that are specific to each activity (like launching
one application or keeping widgets in determined positions), plus the
ability to use multiple virtual desktops inside each &lt;em&gt;activity&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;They integrate with applications that are specifically designed to
take advantage of the desktop environment in question by adapting
colors and themes perfectly to match the general look of the system and
arranging settings in a common location for all applications.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="why-use-a-window-manager-like-i3"&gt;Why use a window manager like i3?&lt;/h3&gt;
&lt;p&gt;Even though desktop environments are user-friendly and include many
goodies, they do have several disadvantages that make window managers
great alternatives.&lt;/p&gt;
&lt;h4 id="less-bloated"&gt;Less bloated&lt;/h4&gt;
&lt;p&gt;Desktop environments are often bloated with many applications
that you may not need but that are nevertheless occupying system
resources as they have many dependencies. For example, if you use
&lt;a href="https://www.thunderbird.net"&gt;Thunderbird&lt;/a&gt; for managing your emails and
your desktop environment is GNOME, try to remove Evolution, the default
application for emails that comes with it&amp;hellip; It&amp;rsquo;s still relatively easy
to disable its processes, but you sometimes have to configure files
manually to satisfy your need for removing clutter.&lt;/p&gt;
&lt;h4 id="lower-memory-and-cpu-consumption"&gt;Lower memory and CPU consumption&lt;/h4&gt;
&lt;p&gt;Other than coming with a set of default applications (more disk space),
the whole environment occupies a lot more memory to run smoothly. On
my modest laptop, I was still experiencing speed issues because the
system was occupying too much RAM when opening heavy applications (lots
of tabs when web browsing, photo editing, loading IDEs like PyCharm
for programming, etc.) and I had 4 GB of RAM installed at the time.
KDE requires at least 600 MB, same is true for GNOME in most recent
versions (but used to be over 1 GB not very long ago, just like for
KDE). Windows, for example, requires more than 1.5 GB of RAM to operate
with basic features. &lt;strong&gt;&lt;code&gt;i3&lt;/code&gt;&lt;/strong&gt; needs less than &lt;strong&gt;~15 MB&lt;/strong&gt; with as many
windows and spaces open as you would ever want. Since there are much
less processes to take care of, CPU consumption is also lower, which is
more noticeable on older machines.&lt;/p&gt;
&lt;h4 id="keyboard-efficiency"&gt;Keyboard efficiency&lt;/h4&gt;
&lt;p&gt;There are obviously ways to go about using keyboard shortcuts for pretty
much anything you want with desktop environments. However, window
managers and especially &lt;code&gt;i3&lt;/code&gt; make this a must, as there is really no
reason to use a mouse for moving windows.&lt;/p&gt;
&lt;p&gt;First of all, windows are &amp;ldquo;stuck&amp;rdquo; in place and never overlap by default.
You can&amp;rsquo;t move them around with a mouse unless they are &amp;ldquo;floating&amp;rdquo;
windows, which means you can separate them to move them around freely
like in most desktop environments. The whole point of using a window
manager like &lt;code&gt;i3&lt;/code&gt; is to maximize screen space, so every window opens
in full screen. Honestly, the only time I ever found the need to use a
floating window with &lt;code&gt;i3&lt;/code&gt; is when using the operating system Windows in
a virtual environment when connecting through RDP with Google Chrome on
Google Cloud Platform (that is, not very often). Other than that, I find
it very practical to split the screen with no overlapping windows, even
with my small 15 inches screen.&lt;/p&gt;
&lt;p&gt;Because windows are managed the way they are in &lt;code&gt;i3&lt;/code&gt;, getting split when
multiple windows are in the same workspace and never overlapping, it
nurtures the good habit of dividing workspaces appropriately to maximize
the space that each application occupies, which is done with keyboard
shortcuts. With (customizable) shortcuts, you can split windows,
move them to other workspaces, change workspaces, open applications
automatically in specific workspaces, etc. Using exclusively the
keyboard to manage the windows becomes a huge time saver, and even more
so when considering the very small footprint required to use the window
manager, making for a lightning fast experience.&lt;/p&gt;
&lt;h4 id="extremely-fast-customization"&gt;Extremely fast customization&lt;/h4&gt;
&lt;p&gt;Once you get past the initial lack of visual appeal and weird way to
move around, you can actually customize many aspects of &lt;code&gt;i3&lt;/code&gt;, including
fonts, mouse bindings, window border decorations, colors, automatic
execution of apps when initiating a session, etc.&lt;/p&gt;
&lt;p&gt;Why is it so fast to customize? Because the configuration is all
contained in one simple text file and you can make a change and reload
the window manager on the fly to see your changes being reflected.
Setting the number of workspaces is as easy as adding or removing a line
(well, as a bare minimum, otherwise it&amp;rsquo;s useful to also bind certain
keyboard shortcuts to move to those newly created workspaces). Setting a
wallpaper is one line, setting a screen lock is another one. Quick and
efficient.&lt;/p&gt;
&lt;h4 id="easy-to-switch-layouts-and-focus"&gt;Easy to switch layouts and focus&lt;/h4&gt;
&lt;p&gt;I actually enjoy the default layout quite a lot, in which there exists
no overlap between windows (they split as needed) and all windows are
visible at the same time in each workspace. If you need to make more
space for a window, you can either &amp;ldquo;focus&amp;rdquo; on the current window, which
will make it full screen and cover every pixel of the screen, or you
can move particular windows to other workspaces. This last option will
automatically resize windows so that they occupy the maximum space
available.&lt;/p&gt;
&lt;p&gt;Besides the default layout, you can also &lt;em&gt;stack&lt;/em&gt; and &lt;em&gt;tab&lt;/em&gt; windows,
depending on how you like to work (it is well worth having a look at the
&lt;a href="https://i3wm.org/docs/userguide.html"&gt;i3 user&amp;rsquo;s guide&lt;/a&gt; to see the many
other features available). Personally, I prefer seeing everything at
once and dividing my work into many workspaces. If you are curious, here
is how I currently have my workspaces set up:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Programming&lt;/strong&gt; — Exclusively for programming purposes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Terminals&lt;/strong&gt; — For working in the terminal, opening another
instance of a terminal text editor, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Web&lt;/strong&gt; — Just for Internet. Always full screen unless I open
some website that requires to open new windows (like banking), which
conveniently split the windows. The web browser automatically launches
in the background when opening a session in &lt;code&gt;i3&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multimedia&lt;/strong&gt; — Editing photos or watching videos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Music&lt;/strong&gt; — &lt;a href="https://github.com/arybczak/ncmpcpp"&gt;ncmpcpp&lt;/a&gt;
(terminal music player) automatically launches in the background when
opening a session.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Experiments&lt;/strong&gt; — I use this workspace when trying to understand
some programming concepts with an interactive IPython console or for
breaking the system in one way or another because I don&amp;rsquo;t know what I&amp;rsquo;m
doing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fix&lt;/strong&gt; — After realizing that sometimes experiments need to be
cleaned up a bit, I now use this workspace exclusively to run tools
in the background, such as &lt;a href="https://www.bleachbit.org"&gt;BleachBit&lt;/a&gt; for
cleaning files or &lt;a href="https://nicolargo.github.io/glances/"&gt;glances&lt;/a&gt;
(similar to the &lt;code&gt;top&lt;/code&gt; command) for watching how the system is doing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Words&lt;/strong&gt; — I use that workspace for reading e-books
or for writing, either in &lt;a href="https://neovim.io/"&gt;Neovim&lt;/a&gt; or
&lt;a href="https://www.libreoffice.org/"&gt;LibreOffice&lt;/a&gt; depending on the task.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tools&lt;/strong&gt; — This workspace is reserved for anything that I
might want to have access to once in a while, like a calendar or
&lt;a href="https://keepassxc.org/"&gt;KeepassXC&lt;/a&gt; for accessing a password database.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;sg&lt;/strong&gt; — I mainly use that workspace to update this very
website, but I also use it for setting up local web servers for
making personal projects in &lt;a href="http://flask.pocoo.org/"&gt;Flask&lt;/a&gt; and
&lt;a href="https://www.djangoproject.com/"&gt;Django&lt;/a&gt; or even just a temporary server
with &lt;code&gt;python -m http.server&lt;/code&gt; to share files with other devices on the
local network.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Only workspaces that contain windows will appear on the screen at any
given time and are automatically created when you access and use them.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="what-does-it-look-like-in-action"&gt;What does it look like in action?&lt;/h2&gt;
&lt;p&gt;Here is a screenshot* of the workspace where this article is being
written (click to open):&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.sglavoie.com/images/posts/0005_using-i3-as-window-manager-for-increased-productivity/i3-example.png"&gt;&lt;img src="https://www.sglavoie.com/images/posts/0005_using-i3-as-window-manager-for-increased-productivity/i3-example.png" alt="i3-example" class="max-size-img-post"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;* &lt;sub&gt;In this particular scenario, the splits on the right side are
intentionally very small as I do not need to read the output, but need
quick access to a terminal to enter commands. Moving back and forth
between windows is a breeze, so that&amp;rsquo;s how I currently handle the
situation.&lt;/sub&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: With &lt;code&gt;Neovim&lt;/code&gt;, &lt;a href="https://www.sglavoie.com/posts/using-embedded-terminals-inside-neovim/"&gt;there is an embedded
terminal&lt;/a&gt;,
which makes things very easy to handle by avoiding splits altogether.
In that case, it is also possible to divide a workflow with tabs inside
&lt;code&gt;Neovim&lt;/code&gt; instead of physically splitting windows.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alternatively&lt;/strong&gt;, instead of splitting windows, a more convenient
solution on smaller screens might be to use &lt;strong&gt;stacking&lt;/strong&gt; windows with
the shortcut &lt;code&gt;$mod + s&lt;/code&gt; in each workspace or, to provide that behavior
by default, the following can be added to i3&amp;rsquo;s configuration file
(defaults in &lt;code&gt;~/.config/i3/config&lt;/code&gt;):&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Set default container layout&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;workspace_layout stacking&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I am not trying to convince myself anymore: I really prefer this
workflow! If you are looking for a
change and would like to maximize both your productivity and your system
resources, &lt;code&gt;i3&lt;/code&gt; is a great window manager to consider. It doesn&amp;rsquo;t seem
very intuitive at first, but I swear it quickly becomes easy to use and
you also end up learning more about how Linux works and set things up
manually (just once!) to your likings. For example, I use Rofi instead
of dmenu to have a window pop-up to select applications or switch to
any window on any workspace&amp;hellip; which was only one line to modify in the
configuration file.&lt;/p&gt;
&lt;p&gt;I have found the following screencasts on YouTube to be quite useful in
learning how to configure &lt;code&gt;i3&lt;/code&gt; (apart from the official documentation
which is very comprehensive):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=j1I63wGcvU4"&gt;i3wm: Jump Start (1/3)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=8-S0cWnLBKg"&gt;i3wm: Configuration (2/3)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=ARKIwOlazKI"&gt;i3wm: How To &amp;ldquo;Rice&amp;rdquo; Your Desktop (3/3)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><dc:creator>Sébastien Lavoie</dc:creator><pubDate>Tue, 08 Jan 2019 11:12:00 -0600</pubDate><guid isPermaLink="false">https://www.sglavoie.com/posts/using-i3-as-a-window-manager-for-increased-productivity/</guid><category>workflow</category><category>i3</category><category>linux</category><category>productivity</category><category>window-manager</category></item><item><title>Bash History Cleaner</title><link>https://www.sglavoie.com/posts/bash-history-cleaner/</link><description>If you ever wanted to automatically clean your Bash history file, here is a working solution written in Python that uses regular expressions to set any kind of pattern you might be looking for.</description><content:encoded>&lt;hr&gt;
&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;This is a Python 3.6+ script that helps to clean the file containing
the Bash history commands. It will remove any line matching a specified
regular expression and can also remove any line starting with an alias.&lt;/p&gt;
&lt;p&gt;The idea behind this small utility was simple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Bash history file (usually located in &lt;code&gt;~/.bash_history&lt;/code&gt;) contains
much of the work one ends up doing in the terminal.&lt;/li&gt;
&lt;li&gt;The history can grow large over time and it becomes more cumbersome to
find interesting information in all that clutter, such as a rarely used
command with specific flags.&lt;/li&gt;
&lt;li&gt;By removing all superfluous commands that are repeated often and which
give no real benefit in certain contexts (such as &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cd&lt;/code&gt;, &lt;code&gt;cat&lt;/code&gt;,
etc.), the history is much cleaner and easier to navigate and actually
becomes much more useful in my opinion.&lt;/li&gt;
&lt;li&gt;True, it will be harder to follow the bread crumbs for everything
you did, but I haven&amp;rsquo;t come across a situation where having access
to yet another empty &lt;code&gt;ls&lt;/code&gt; or &lt;code&gt;cd&lt;/code&gt; has proven necessary and reading
&lt;code&gt;.bash_history&lt;/code&gt; doesn&amp;rsquo;t make for a great narrative story either.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="make-history-in-a-big-way"&gt;Make history in a big way&lt;/h2&gt;
&lt;p&gt;I took advantage of the fact that the history can be cleaned with the
script you are about to see and set up what is known as an &lt;em&gt;eternal
history&lt;/em&gt; which, as it sounds like, can grow infinitely big! All you have
to do is append the following lines to the file &lt;code&gt;~/.bashrc&lt;/code&gt;:&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Eternal bash history.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# ---------------------&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Undocumented feature which sets the size to &amp;#34;unlimited&amp;#34;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# http://stackoverflow.com/questions/9457233/unlimited-bash-history&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;HISTFILESIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;HISTSIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;-1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;HISTTIMEFORMAT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;[%F %T] &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Change the file location because certain bash sessions truncate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# .bash_history file upon close.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# http://superuser.com/questions/575479/bash-history-truncated-to-500-lines-on-each-login&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nv"&gt;HISTFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/.bash_eternal_history
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Force prompt to write history after every command.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# http://superuser.com/questions/20900/bash-history-loss&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;PROMPT_COMMAND&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;history -a; &lt;/span&gt;&lt;span class="nv"&gt;$PROMPT_COMMAND&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2 id="bash-history-cleaner"&gt;Bash History Cleaner&lt;/h2&gt;
&lt;p&gt;And here is the script in question *. It comes in two files that need to be in the same directory:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One is a Python file that needs to be launched from the terminal with
Python 3.&lt;/li&gt;
&lt;li&gt;The other file, &lt;code&gt;settings.json&lt;/code&gt;, is a JSON file used to store the
settings of the script, which will be detailed below.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;* &lt;sub&gt;Improvements to the original script can be found on &lt;a
href="https://github.com/sglavoie/python-utilities/tree/main/bash_history_cleaner"&gt;Github&lt;/a&gt;. To keep this
article a bit more readable, the original version is shown.&lt;/sub&gt;&lt;/p&gt;
&lt;h2 id="bash_history_cleanerpy"&gt;&lt;code&gt;bash_history_cleaner.py&lt;/code&gt;&lt;/h2&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;python&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;Python script that helps to clean the file containing the Bash history
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;commands.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;Note: Requires Python 3.6+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;It will remove any line matching a specified regular expression and can
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;also remove any line starting with an alias.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;Description of available settings in `settings.json`:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;home_directory&amp;#34;: Absolute path to user&amp;#39;s home directory.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;history_file&amp;#34;: Name of file where the history will be cleaned up.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;aliases_file&amp;#34;: Name of file where Bash aliases are set up.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;ignore_patterns&amp;#34;: List of patterns to ignore in `history_file`.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; Each line where a pattern is found will be deleted.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; → Patterns are specified as regular expressions.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;add_aliases&amp;#34;: Boolean. If set to `true`, aliases from `aliases_file`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; will be added to `ignore_patterns`.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;aliases_match_greedily&amp;#34;:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; Boolean. If set to `true`, any line in `history_file`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; starting with an alias in `aliases_file` will be
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; deleted. If set to `false`, delete line if the alias is
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; the content of the whole line (with optional space at
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; the end): `false` matches &amp;#34;^alias$&amp;#34; or &amp;#34;^alias $&amp;#34; only.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;backup_history&amp;#34;: Boolean. If set to `true`, `history_file` will be backed
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; up in the same directory with a name ending in .bak
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; based on the current date.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; &amp;#34;delete_logs_without_confirming&amp;#34;:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; Boolean. If set to `true`, script with flag `-c` will
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; automatically delete all the backup files found for
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; `history_file`.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;argparse&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;fileinput&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;glob&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_current_path&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&amp;#39;Returns the current working directory relative to where this script
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; is being executed.&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parents&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;user_says_yes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&amp;#39;Check if user input is either &amp;#39;y&amp;#39; or &amp;#39;n&amp;#39;. Returns a boolean.&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;choice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;choice&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;y&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;choice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;choice&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;choice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Please enter either &amp;#39;y&amp;#39; or &amp;#39;n&amp;#39;.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;choice&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;delete_logs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;history_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&amp;#39;Delete log files in `home_directory` based on `history_file`.&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Retrieve a list of all matching log files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;log_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;history_file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;_*.bak&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;log_files&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;There is no log file to delete.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Log files found in &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;home_directory&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;log_file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;log_files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;delete_logs_without_confirming&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;log_file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;log_files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Log files deleted.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;Do you want to delete those log files? [y/n] &amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user_says_yes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;log_file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;log_files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Log files deleted.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Operation aborted.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_date_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&amp;#39;Return date formatted string to backup a file.&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;today&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;_%Y%m&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s1"&gt;_%H%M%S.bak&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_settings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&amp;#39;Load settings in the script. Return them as a dictionary.&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;r&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;read_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_list_aliases&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bash_aliases_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&amp;#39;Retrieve the name of all the aliases specified in `bash_aliases_file`.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; Return aliases as a list of strings formatted as regular expressions.&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;match_whole_line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;aliases_match_greedily&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bash_aliases_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;splitlines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# one alias per line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;aliases_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Get the actual alias in each line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Use negative lookbehind to remove &amp;#39;alias &amp;#39; at the beginning.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Matches anything after that is a dot, digit, underscore&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# or letter (will stop at the equal sign: alias blah=&amp;#39;...&amp;#39;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;(?&amp;lt;!not )alias ([\.\w]*)&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# If for some reason the alias cannot be extracted, skip it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# If search doesn&amp;#39;t match, it&amp;#39;s of type None and won&amp;#39;t work&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;match_whole_line&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Match the whole line if it starts with the alias.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;^&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;( )?$|^&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt; .*&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Will match only when alias is the whole content of the line,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# followed by optional space.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;^&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;( )?$&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Escape dots in alias&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;maketrans&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;\.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;aliases_list&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;aliases_list&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;clean_bash_history&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;history_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&amp;#39;Modify in place `history_file` by removing every line where
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; `ignore_patterns` is found.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; Optionally, add a list of aliases to `ignore_patterns` with
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s1"&gt; `aliases` based on the value of `add_aliases` in settings.json.&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;backup_history&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;backup_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;generate_date_string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;file_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fileinput&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FileInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;history_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;backup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;backup_str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;file_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fileinput&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FileInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;history_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;file_input&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;has_match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ignore_patterns&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;matched&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;matched&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;has_match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# If no match is found (nothing to ignore), print the line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# back into the file. Otherwise, it will be empty.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;has_match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Line already has carriage return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;launch_cleanup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;history_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aliases_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&amp;#39;Main function that launches the cleanup process.&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;bash_aliases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;add_aliases&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;bash_aliases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_list_aliases&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;aliases_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# add aliases to list of patterns to ignore&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ignore_patterns&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bash_aliases&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;FileNotFoundError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;File not found: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;aliases_file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;clean_bash_history&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;history_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;FileNotFoundError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;File not found: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;history_file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SETTINGS_FILE_PATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_current_path&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;settings.json&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SETTINGS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;load_settings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SETTINGS_FILE_PATH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ALIASES_FILE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SETTINGS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;home_directory&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;SETTINGS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;aliases_file&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;HISTORY_FILE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SETTINGS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;home_directory&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;/&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;SETTINGS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;history_file&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# initiate the parser to check all the arguments passed to the script&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;PARSER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ArgumentParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;PARSER&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;-c&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;--clear&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Delete all log files&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;store_true&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# read arguments from the command line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ARGUMENTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PARSER&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse_args&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ARGUMENTS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;delete_logs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SETTINGS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HISTORY_FILE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;launch_cleanup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SETTINGS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HISTORY_FILE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ALIASES_FILE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="settingsjson"&gt;&lt;code&gt;settings.json&lt;/code&gt;&lt;/h2&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;json&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;home_directory&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/home/sglavoie&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;history_file&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;.bash_eternal_history&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;add_aliases&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;aliases_file&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;.bash_aliases&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;aliases_match_greedily&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;backup_history&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;delete_logs_without_confirming&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;ignore_patterns&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^\\#\\d+&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^(\\.\\/)?pip$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^(\\.\\/)?python.*$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^\\.\\.$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^alias&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^cd &amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^cd$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^cd..$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^fg$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^df( )?&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^du( )?&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^exit$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^git branch&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^git checkout master&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^git log$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^git push$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^git status$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^git stauts$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^kill \\d+.*&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^ls -a$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^ls$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^make|make install$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^man &amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^pelican( )?$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^pip install -r requirements.txt&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^pip.* list|pip.* show$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^source &amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^sudo apt-get autoclean|sudo apt-get autoremove$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^sudo apt-get dist-upgrade|sudo apt-get update$&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;^which &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2 id="description-of-available-settings-in-settingsjson"&gt;Description of available settings in &lt;code&gt;settings.json&lt;/code&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Name of setting&lt;/th&gt;
 &lt;th&gt;Description&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;home_directory&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Absolute path to user&amp;rsquo;s home directory.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;history_file&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Name of file where the history will be cleaned up.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;aliases_file&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Name of file where Bash aliases are set up.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;ignore_patterns&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;List of patterns to ignore in &lt;code&gt;history_file&lt;/code&gt;. Each line where a pattern is found will be deleted. Patterns are specified as regular expressions.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;add_aliases&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Boolean. If set to &lt;code&gt;true&lt;/code&gt;, aliases from &lt;code&gt;aliases_file&lt;/code&gt; will be added to &lt;code&gt;ignore_patterns&lt;/code&gt;. (Default: &lt;code&gt;true&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;aliases_match_greedily&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Boolean. If set to &lt;code&gt;true&lt;/code&gt;, any line in &lt;code&gt;history_file&lt;/code&gt; starting with an alias in &lt;code&gt;aliases_file&lt;/code&gt; will be deleted. If set to &lt;code&gt;false&lt;/code&gt;, delete line if the alias is the content of the whole line (with optional space at the end): &lt;code&gt;false&lt;/code&gt; matches &amp;ldquo;^alias$&amp;rdquo; or &amp;ldquo;^alias $&amp;rdquo; only.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;backup_history&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Boolean. If set to &lt;code&gt;true&lt;/code&gt;, &lt;code&gt;history_file&lt;/code&gt; will be backed up in the same directory with a name ending in .bak based on the current date. (Default: &lt;code&gt;true&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;delete_logs_without_confirming&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Boolean. If set to &lt;code&gt;true&lt;/code&gt;, script with flag &lt;code&gt;-c&lt;/code&gt; will automatically delete all the backup files found for &lt;code&gt;history_file&lt;/code&gt;. (Default: &lt;code&gt;false&lt;/code&gt;)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="anecdotal-evidence-of-satisfying-performances"&gt;Anecdotal evidence of satisfying performances&lt;/h2&gt;
&lt;p&gt;Performance-wise, this scans ~8,300 lines per second on my modest Intel
Core i5 laptop with files of over 200,000 lines long. Not that I type so
much stuff in the terminal: I just duplicated many lines.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This is a simple solution to an nonexistent problem, but it was
in the end very instructive to me nonetheless. You may even find
a use for it! Otherwise, you might use the same functions for
other files such as logs! If you would like to take a closer look
at the source in a more convenient way, you can find the code &lt;a href="https://github.com/sglavoie/python-utilities/tree/main/bash_history_cleaner"&gt;available on Github&lt;/a&gt;.&lt;/p&gt;</content:encoded><dc:creator>Sébastien Lavoie</dc:creator><pubDate>Sun, 23 Dec 2018 19:35:00 -0600</pubDate><guid isPermaLink="false">https://www.sglavoie.com/posts/bash-history-cleaner/</guid><category>automation</category><category>bash</category><category>linux</category><category>python</category><category>regex</category><category>script</category><category>terminal</category></item><item><title>Aliases: Also Known as Terminal User's Best Friends</title><link>https://www.sglavoie.com/posts/aliases-also-known-as-terminal-users-best-friends/</link><description>Here are presented a few terminal aliases that I find myself using regularly.</description><content:encoded>&lt;hr&gt;
&lt;h2 id="some-aliases-that-i-find-useful"&gt;Some aliases that I find useful&lt;/h2&gt;
&lt;hr&gt;
&lt;blockquote&gt;
 &lt;p&gt;In all the following examples, the dollar sign &lt;code&gt;$&lt;/code&gt; at the beginning of
commands represents the prompt, it should not be typed.&lt;/p&gt;

&lt;/blockquote&gt;&lt;h3 id="general-purpose"&gt;General-purpose&lt;/h3&gt;
&lt;hr&gt;
&lt;h4 id="list-all-aliases"&gt;List all aliases&lt;/h4&gt;
&lt;div class="code-block" data-prompted&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="code-block__prompt"&gt;$ &lt;/span&gt;alias&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Prints all of your aliases. If you have plenty of those, you might
prefer to pipe this command with &lt;code&gt;less&lt;/code&gt; to get a nice pager that allows
you to easily nagivate them:&lt;/p&gt;
&lt;div class="code-block" data-prompted&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="code-block__prompt"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; less&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h4 id="setting-an-alias-in-bash_aliases"&gt;Setting an alias in &lt;code&gt;~/.bash_aliases&lt;/code&gt;&lt;/h4&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;clear&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This would set &lt;code&gt;c&lt;/code&gt; as a shortcut to &lt;code&gt;clear&lt;/code&gt;. In order to use the
newly created alias, you would have to close the terminal or type the
following command in the terminal:&lt;/p&gt;
&lt;div class="code-block" data-prompted&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="code-block__prompt"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bash_aliases&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h4 id="clear-the-screen"&gt;Clear the screen&lt;/h4&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;clear&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I like being absorbed into the emptiness of the terminal, so this one
comes in handy to tidy up the work space.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id="reset-the-terminal"&gt;Reset the terminal&lt;/h4&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;re&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;tput reset&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If for some reasons the terminal displays badly or display funky
characters, it can usually be reset this way.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id="exit-from-the-terminal"&gt;Exit from the terminal&lt;/h4&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;q&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;exit&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For exiting the terminal as if you were still in Vim!&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id="display-all-file-extensions-recursively-from-the-current-directory"&gt;Display all file extensions recursively from the current directory&lt;/h4&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;allextensions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;find . -type f -name &amp;#39;*.*&amp;#39; | sed &amp;#39;s|.*\.||&amp;#39; | sort -u&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;It comes in handy to spot if a file shouldn&amp;rsquo;t be there or to check for
lower or uppercase extensions.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id="find-text-inside-files-including-filenames"&gt;Find text inside files, including filenames&lt;/h4&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;findinfiles&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ag --nobreak --nonumbers --noheading . | fzf&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In this example, the alias is set up with
&lt;a href="https://github.com/ggreer/the_silver_searcher"&gt;ag&lt;/a&gt;, a fast
code-searching tool and &lt;a href="https://github.com/junegunn/fzf"&gt;fzf&lt;/a&gt;, a great
fuzzy finder.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id="reboot-and-shutdown-the-system"&gt;Reboot and shutdown the system&lt;/h4&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;reboot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;systemctl reboot&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;shutdown&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;systemctl poweroff&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This will reboot or power off the system without needing root privileges
in most working conditions.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id="list-and-sort-files-and-directories-by-modification-time"&gt;List and sort files and directories by modification time&lt;/h4&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;treeold&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;tree -hDF | less&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This requires the command &lt;code&gt;tree&lt;/code&gt; to be installed. The parameters are
(descriptions taken from &lt;code&gt;man tree&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-h&lt;/code&gt;: Print the size of files in a human readable way.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-D&lt;/code&gt;: Print the date of the last modification time.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-F&lt;/code&gt;: Append a &amp;lsquo;&lt;code&gt;/&lt;/code&gt;&amp;rsquo; for directories, a &amp;lsquo;&lt;code&gt;=&lt;/code&gt;&amp;rsquo; for socket files, a &amp;lsquo;&lt;code&gt;\*&lt;/code&gt;&amp;rsquo;
for executable files, a &amp;lsquo;&lt;code&gt;&amp;gt;&lt;/code&gt;&amp;rsquo; for doors (Solaris) and a &amp;lsquo;&lt;code&gt;|&lt;/code&gt;&amp;rsquo; for
FIFO&amp;rsquo;s, as per &lt;code&gt;ls -F&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id="open-files-quickly-with-default-applications"&gt;Open files quickly with default applications&lt;/h4&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;o&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;xdg-open&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This will open files and URLs specified as argument in the default
application detected.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id="moving-around"&gt;Moving around&lt;/h4&gt;
&lt;p&gt;If you are going to be working on projects for some time and require to
&lt;code&gt;cd&lt;/code&gt; into them, I have found the following to be useful:&lt;/p&gt;
&lt;div class="code-block" data-prompted&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="code-block__prompt"&gt;$ &lt;/span&gt;cdnameOfProject &lt;span class="c1"&gt;# instead of having to do cd /path/to/project/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="code-block__prompt"&gt;$ &lt;/span&gt;&lt;span class="c1"&gt;# More examples:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="code-block__prompt"&gt;$ &lt;/span&gt;cdcodeabbey &lt;span class="c1"&gt;# For codeabbey.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="code-block__prompt"&gt;$ &lt;/span&gt;cdhackerrank &lt;span class="c1"&gt;# For hackerrank.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="code-block__prompt"&gt;$ &lt;/span&gt;cdeuler &lt;span class="c1"&gt;# For projecteuler.net&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="code-block__prompt"&gt;$ &lt;/span&gt;cdgit &lt;span class="c1"&gt;# For all Github repositories&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This is not advanced by any means, but it helps quite regularly! Since
you can take advantage of tab completion, you can type &lt;code&gt;cd&lt;/code&gt; (without
adding a space) and then press &lt;code&gt;TAB&lt;/code&gt; key to autocomplete the aliases.&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; ...&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cd ../..&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Make it easier to navigate into deep directory structures by basically
doing &lt;code&gt;cd .. &amp;amp;&amp;amp; cd ..&lt;/code&gt; to go back up two directories at once.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id="listing-files"&gt;Listing files&lt;/h4&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;l&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ls -CFh&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;la&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ls -Ah&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;ll&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ls -ahlF&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;ls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ls --color=auto&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Different ways to set up the command ls to quickly see the needed files.
The parameters are (descriptions taken from &lt;code&gt;man ls&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-A&lt;/code&gt;: &lt;em&gt;Do not list implied &lt;code&gt;.&lt;/code&gt; and &lt;code&gt;..&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-C&lt;/code&gt;: &lt;em&gt;List entries by columns.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-F&lt;/code&gt;: &lt;em&gt;Append indicator (one of &lt;code&gt;\*/=&amp;gt;@|&lt;/code&gt;) to entries.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-a&lt;/code&gt;: &lt;em&gt;Do not ignore entries starting with .&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-h&lt;/code&gt;: &lt;em&gt;With &lt;code&gt;-l&lt;/code&gt; and/or &lt;code&gt;-s&lt;/code&gt;, print human readable sizes (e.g., 1K 234M 2G).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-l&lt;/code&gt;: &lt;em&gt;Use a long listing format.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="python-related"&gt;Python-related&lt;/h3&gt;
&lt;hr&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;aNameOfProject&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;source /path/to/project/bin/activate&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;aa&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;source ~/Programming/anaconda3/bin/activate&amp;#39;&lt;/span&gt; &lt;span class="c1"&gt;# Example using Anaconda distribution&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The purpose is to activate a specific virtual environment quickly. The
command &lt;code&gt;cd&lt;/code&gt; could be added to go to the related project also:&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;gNameOfProject&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;cd /path/to/project/ &amp;amp;&amp;amp; ./.venv/bin/activate&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Where &lt;code&gt;.venv&lt;/code&gt; would be the name of the virtual environment.&lt;/p&gt;
&lt;p&gt;I like to &lt;strong&gt;a&lt;/strong&gt;ctivate environments starting aliases with &lt;code&gt;a&lt;/code&gt; and &lt;strong&gt;go&lt;/strong&gt;
and activate at the same time starting aliases with &lt;code&gt;g&lt;/code&gt;. This way, it
feels like I am speaking the Vim language (&lt;code&gt;cw&lt;/code&gt; for &lt;strong&gt;c&lt;/strong&gt;hange &lt;strong&gt;w&lt;/strong&gt;ord,
for example).&lt;/p&gt;
&lt;hr&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;da&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;deactivate&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This will deactivate a virtual environment.&lt;/p&gt;
&lt;hr&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;p36&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;python3.6&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;p&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;python3.7&amp;#39;&lt;/span&gt; &lt;span class="c1"&gt;# Simply using `p` for main version of Python&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Practical way to quickly open the desired Python version.&lt;/p&gt;
&lt;hr&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;bash&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;alias&lt;/span&gt; &lt;span class="nv"&gt;pyclean&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;find . -regex &amp;#34;.*\(__pycache__\|\.py[co]\)&amp;#34; -delete&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This will delete recursively all files and directories that match one of
the following patterns in their name: &lt;code&gt;__pycache__&lt;/code&gt;, &lt;code&gt;.pyc&lt;/code&gt; or &lt;code&gt;.pyo&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I hope you will find at least one alias to improve your productivity.
Of course, you are welcome to chime in with your own suggestions!&lt;/p&gt;</content:encoded><dc:creator>Sébastien Lavoie</dc:creator><pubDate>Sat, 08 Dec 2018 13:52:00 -0600</pubDate><guid isPermaLink="false">https://www.sglavoie.com/posts/aliases-also-known-as-terminal-users-best-friends/</guid><category>tips-and-tricks</category><category>aliases</category><category>bash</category><category>linux</category><category>productivity</category><category>terminal</category></item></channel></rss>