<?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: Shell</title><link>https://www.sglavoie.com/tags/shell/</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/shell/feed.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Sat, 30 Nov 2019 13:22:00 -0600</lastBuildDate><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>fzf - A Fuzzy Finder to Accomplish Anything</title><link>https://www.sglavoie.com/posts/fzf-a-fuzzy-finder-to-accomplish-anything/</link><description>Search and, most importantly, finally find what you are looking for on your machine. If you rely on the terminal a lot, fzf may well be capable of speeding up your productivity!</description><content:encoded>&lt;hr&gt;
&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I know people who make such a mess when &lt;em&gt;not&lt;/em&gt; organizing their files and
directories appropriately on their system, they would benefit greatly
from &lt;code&gt;fzf&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="what-is-fzf"&gt;What is fzf?&lt;/h2&gt;
&lt;p&gt;From the &lt;a href="https://github.com/junegunn/fzf"&gt;official GitHub page&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
 &lt;p&gt;fzf is a general-purpose command-line fuzzy finder. It&amp;rsquo;s an
interactive Unix filter for command-line that can be used with any list;
files, command history, processes, hostnames, bookmarks, git commits,
etc.&lt;/p&gt;

&lt;/blockquote&gt;&lt;hr&gt;
&lt;h2 id="terminal-aliases"&gt;Terminal aliases&lt;/h2&gt;
&lt;p&gt;One of the main uses of &lt;code&gt;fzf&lt;/code&gt; is from the terminal. Being so flexible
to use, it can be combined with all kinds of commands with the help
of pipes (&lt;code&gt;|&lt;/code&gt;) to bend it to your desires. Here are some aliases I am
currently using that undoubtedly improve my terminal workflow.&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;##### Functions&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;# Select a configuration file with fzf and open it with Neovim&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conf&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; du -a ~/.dotfiles/* ~/.config/* &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; fzf &lt;span class="p"&gt;|&lt;/span&gt; xargs -r nvim &lt;span class="p"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Select a file from current folder and recursively with fzf and open it with Neovim&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;se&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; du -a ./* &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; fzf &lt;span class="p"&gt;|&lt;/span&gt; xargs -r nvim &lt;span class="p"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Select a file recursively from university folder with fzf and open it with default app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sc&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; du -a ~/Dropbox/university/* &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;&amp;#39;{print $2}&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; fzf &lt;span class="p"&gt;|&lt;/span&gt; xargs -r xdg-open &lt;span class="p"&gt;;&lt;/span&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;p&gt;The first alias, &lt;code&gt;conf&lt;/code&gt; (short for &lt;em&gt;configuration&lt;/em&gt;), allows to search
only within the two folders specified for configuration files, which
makes it pop almost instantaneously since it doesn&amp;rsquo;t have to scan files
scattered anywhere else. You can then type anything that partially
matches a file path and even include slashes (&lt;code&gt;/&lt;/code&gt;) in your match if you
know in which directories to look. You can then type &lt;code&gt;Enter&lt;/code&gt; to open the
file with your favorite text editor (here set to &lt;code&gt;nvim&lt;/code&gt;) or type &lt;code&gt;CTRL + c&lt;/code&gt; to abort the command.&lt;/p&gt;
&lt;p&gt;The other aliases work in a similar fashion. &lt;code&gt;se&lt;/code&gt; (short for &lt;em&gt;search&lt;/em&gt;)
will simply search recursively for any kind of files in the current
directory and open the selected file in a text editor. Of course,
certain file types can be excluded and everything else can be tweaked
with more piping power. In the case of the third alias, &lt;code&gt;sc&lt;/code&gt; (short for
&lt;em&gt;school&lt;/em&gt;), it will also search recursively for any kind of file in the
&lt;code&gt;university&lt;/code&gt; folder and will open it with the default application set to
open that kind of file (video, image, text, PDF, etc.).&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="vimneovim-integration"&gt;Vim/Neovim integration&lt;/h2&gt;
&lt;p&gt;Using &lt;a href="https://github.com/junegunn/vim-plug"&gt;Vim-Plug&lt;/a&gt; from the same
author as &lt;code&gt;fzf&lt;/code&gt; is as easy as adding the following to Vim/Neovim&amp;rsquo;s
configuration file. First, we make sure that &lt;code&gt;fzf&lt;/code&gt; is available on the
system and install it if it&amp;rsquo;s not. Then, we install the &lt;code&gt;fzf.vim&lt;/code&gt; plugin
to integrate fzf in Vim and optionally, we may configure more options so
that &lt;code&gt;fzf&lt;/code&gt; can be used more optimally, which can be found on the &lt;a href="https://github.com/junegunn/fzf.vim"&gt;GitHub
plugin page&lt;/a&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;vim&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-vim" data-lang="vim"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;Plug&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;junegunn/fzf&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; { &lt;span class="s1"&gt;&amp;#39;dir&amp;#39;&lt;/span&gt;: $&lt;span class="nx"&gt;HOME&lt;/span&gt; . &lt;span class="s1"&gt;&amp;#39;/.fzf&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;do&amp;#39;&lt;/span&gt;: &lt;span class="s1"&gt;&amp;#39;./install --all&amp;#39;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;Plug&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;junegunn/fzf.vim&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;#34;&amp;#34;&amp;#34;&amp;#34;&amp;#34; [ FZF ]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;#34; Allows fzf to ignore patterns in .gitignore&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;let&lt;/span&gt; $&lt;span class="nx"&gt;FZF_DEFAULT_COMMAND&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ag -g &amp;#34;&amp;#34;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;#34; Mapping selecting mappings&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;nmap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;leader&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;plug&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nx"&gt;fzf&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;n&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="nx"&gt;xmap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;leader&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;plug&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nx"&gt;fzf&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;x&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="nx"&gt;omap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;leader&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;plug&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nx"&gt;fzf&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;o&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="c"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;#34; Insert mode completion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;imap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;plug&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nx"&gt;fzf&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;word&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="nx"&gt;imap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;plug&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nx"&gt;fzf&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;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="nx"&gt;imap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;plug&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nx"&gt;fzf&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ag&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="nx"&gt;imap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;plug&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nx"&gt;fzf&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&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="c"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;#34; Advanced customization using autoload functions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;#34; (expand word completing window)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;inoremap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;fzf&lt;/span&gt;#&lt;span class="nx"&gt;vim&lt;/span&gt;#&lt;span class="nx"&gt;complete&lt;/span&gt;#&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;{&lt;span class="s1"&gt;&amp;#39;left&amp;#39;&lt;/span&gt;: &lt;span class="s1"&gt;&amp;#39;20%&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="c"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;#34; Make use of fzf command instead of CtrlP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;map&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;C&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; :&lt;span class="nx"&gt;FZF&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;cr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;#34;&amp;#34;&amp;#34; [ / FZF ]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="working-with-neovim"&gt;Working with Neovim&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;fzf&lt;/code&gt; really shines when used with Neovim as it is extremely fast,
especially when configured with
&lt;a href="https://github.com/ggreer/the_silver_searcher"&gt;The Silver Searcher&lt;/a&gt;
which deserves its own article. It
integrates with core functionality of Vim and makes it easy to find what
you are looking for.&lt;/p&gt;
&lt;p&gt;From the above configuration, for instance:&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;vim&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-vim" data-lang="vim"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;nmap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;leader&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;plug&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nx"&gt;fzf&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;maps&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;n&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;p&gt;This allows to search for existing mappings and commands, which can be
faster than diving in the help pages when looking for a quick reference.&lt;/p&gt;
&lt;p&gt;This one in insert mode is very handy:&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;vim&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-vim" data-lang="vim"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;imap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;plug&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="nx"&gt;fzf&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;word&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;p&gt;Without affecting keyword completion with &lt;code&gt;CTRL + n&lt;/code&gt; and &lt;code&gt;CTRL + p&lt;/code&gt;
(unless you have &lt;code&gt;set complete+=k&lt;/code&gt; in your configuration file), you can
complete words from a custom dictionary of your choice with &lt;code&gt;CTRL + x CTRL + k&lt;/code&gt;. The window that appears can be moved and resized, which is
what is happening here:&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;vim&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-vim" data-lang="vim"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;inoremap&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;fzf&lt;/span&gt;#&lt;span class="nx"&gt;vim&lt;/span&gt;#&lt;span class="nx"&gt;complete&lt;/span&gt;#&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;{&lt;span class="s1"&gt;&amp;#39;left&amp;#39;&lt;/span&gt;: &lt;span class="s1"&gt;&amp;#39;20%&amp;#39;&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;p&gt;In the same way, file paths can be completed from the current working
directory &lt;code&gt;CTRL + x CTRL + f&lt;/code&gt; and existing lines can be quickly inserted
with &lt;code&gt;CTRL + x CTRL + l&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.sglavoie.com/images/posts/0016_a_fuzzy_file_finder_to_accomplish_anything/fzf_autocompletion.png"&gt;&lt;img src="https://www.sglavoie.com/images/posts/0016_a_fuzzy_file_finder_to_accomplish_anything/fzf_autocompletion.png" alt="fzf_line_autocompletion" class="max-size-img-post"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Finally, I use &lt;code&gt;fzf&lt;/code&gt; to open any file quickly from the working directory
inside Neovim with the mapping &lt;code&gt;CTRL + p&lt;/code&gt;, which replaces the CtrlP
plugin and can work much faster on larger codebases.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;There is much more that can be done with it and I am barely scratching
the surface here. Luke Smith shared
&lt;a href="https://www.youtube.com/watch?v=vt33Hp-4RXg"&gt;a great video&lt;/a&gt; that will
complement the information from this post nicely with a more technical
approach. Highly recommended to see more practical ways to use this
superb piece of software!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://lukesmith.xyz/"&gt;Luke Smith&lt;/a&gt; also makes a strong point of
combining &lt;code&gt;fzf&lt;/code&gt; with &lt;a href="https://tools.suckless.org/dmenu/"&gt;dmenu&lt;/a&gt;, a tool
that I described succinctly in
&lt;a href="https://www.sglavoie.com/posts/suckless-minimalist-tools-that-work-great/"&gt;a previous article&lt;/a&gt;.&lt;/p&gt;</content:encoded><dc:creator>Sébastien Lavoie</dc:creator><pubDate>Fri, 24 May 2019 10:56:00 -0500</pubDate><guid isPermaLink="false">https://www.sglavoie.com/posts/fzf-a-fuzzy-finder-to-accomplish-anything/</guid><category>workflow</category><category>plugin</category><category>productivity</category><category>shell</category><category>terminal</category></item></channel></rss>