11-13-2018, 05:30 PM
Beyond Finding Stuff with the Linux find Command
<div style="margin: 5px 5% 10px 5%;"><img src="http://www.sickgaming.net/blog/wp-content/uploads/2018/11/beyond-finding-stuff-with-the-linux-find-command.jpg" width="1497" height="837" title="" alt="" /></div><div><div><img src="http://www.sickgaming.net/blog/wp-content/uploads/2018/11/beyond-finding-stuff-with-the-linux-find-command.jpg" class="ff-og-image-inserted" /></div>
<p>Continuing the quest to become a command-line power user, in this installment, we will be taking on the <code>find</code> command.</p>
<p>Jack Wallen already covered <a href="https://www.linux.com/learn/intro-to-linux/2017/3/how-search-files-linux-command-line">the basics of <code>find</code></a> in an article published recently here on Linux.com. If you are completely unfamiliar with <code>find</code>, please read that article first to come to grips with the essentials.</p>
<p>Done? Good. Now, you need to know that <code>find</code> can be used to do much more than just for search for something, in fact you can use it to search for two or three things. For example:</p>
<pre> find path/to/some/directory/ -type f -iname '*.svg' -o -iname '*.pdf' </pre>
<p>This will cough up all the files with the extensions <code>svg</code> (or <code>SVG</code>) and <code>pdf</code> (or <code>PDF</code>) in the <i>path/to/directory</i> directory. You can add more things to search for using the <code>-o</code> over and over.</p>
<p>You can also search in more than one directory simultaneously just be adding them to the <i>route</i> bit of the command. Say you want to see what is eating up all the space on your hard drive:</p>
<pre> find $HOME /var /etc -size +500M </pre>
<p>This will return all the files bigger than 500 Megabytes (<code>-size +500M</code>) in your home directory, <i>/var</i> and <i>/etc</i>.</p>
<p>Additionally, <code>find</code> also lets you do stuff with the files it… er… finds. For example, you can use the <code>-delete</code> action to remove everything that comes up in a search. Now, be careful with this one. If you run</p>
<pre> # WARNING: DO NOT TRY THIS AT $HOME find . -iname "*" -delete </pre>
<p><code>find</code> will erase everything in the current directory (<code>.</code> is shorthand for “<i>the current directory</i>“) and everything in the subdirectories under it, and then the subdirectories themselves, and then there will be nothing but emptiness and an unbearable feeling that something has gone terribly wrong.</p>
<p>Please do not put it to the test.</p>
<p>Instead, let’s look at some more constructive examples…</p>
<h3>Moving Stuff Around</h3>
<p>Let’s say you have bunch of pictures of Tux the penguin in several formats and spread out over dozens of directories, all under your <i>Documents/</i> folder. You want to bring them all together into one directory (<i>Tux/</i>) to create a gallery you can revel in:</p>
<pre> find $HOME/Documents/ \( -iname "*tux*png" -o -iname "*tux*jpg" -o -iname "*tux*svg" \) -exec cp -v '{}' $HOME/Tux/ \; </pre>
<p>Let’s break this down:</p>
<p>Once you have the basics of modifying files using <code>find</code> under your belt, you will discover all sorts of situations where it comes in handy. For example…</p>
<h3>A Terrible Mish-Mash</h3>
<p>Client X has sent you a zip file with important documents and images for the new website you are working on for them. You copy the zip into your <i>ClientX</i> folder (which already contains dozens of files and directories) and uncompress it with <code>unzip newwebmedia.zip</code> and, gosh darn it, the person who made the zip file didn’t compress the directory itself, but the contents in the directory. Now all the images, text files and subdirectories from the zip are all mixed up with the original contents of you folder, that contains more images, text files, and subdirectories.</p>
<p>You could try and remember what the original files were and then move or delete the ones that came from the zip archive. But with dozens of entries of all kinds, you are bound to get mixed up at some point and forget to move a file, or, worse, delete one of your original files.</p>
<p>Looking at the files’ dates (<code>ls -la *</code>) won’t help either: the Zip program keeps the dates the files were originally created, not when they were zipped or unzipped. This means a “new” file from the zip could very well have a date prior to some of the files that were already in the folder when you did the unzipping.</p>
<p>You probably can guess what comes next: <code>find</code> to the rescue! Move into the directory (<code>cd path/to/ClientX</code>), make a new directory where you want the new stuff to go (<code>mkdir NewStuff</code>), and then try this:</p>
<pre> find . -cnewer newwebmedia.zip -exec mv '{}' NewStuff \; </pre>
<p>Breaking that down:</p>
<ul>
<li>The period (<code>.</code>) tells <code>find</code> to do its thing in the current directory.</li>
<li><code>-cnewer</code> tells <code>find</code> to look for files that have been changed at the same time or after a certain file you give as reference. In this case the reference file is <code>newwebmedia.zip</code>. If you copied the file over at 12:00 and then unpacked it at 12:01, all the files that you unpacked will be tagged as changed at 12:01, that is, after <code>newwebmedia.zip</code> and will match that criteria! And, as long as you didn’t change anything else, they will be the only files meeting that criteria.</li>
<li>The <code>-exec</code> part of the instruction simply tells <code>find</code> to move the files and directories to the <code>NewStuff/</code> directory, thus cleaning up the mess.</li>
</ul>
<p>If you are unsure of anything <code>find</code> may do, you can swap <code>-exec</code> for <code>-ok</code>. The <code>-ok</code> option forces <code>find</code> to check with you before it runs the command you have given it. Accept an action by typing <i>y</i> or reject it with <i>n</i>.</p>
<h3>Next Time</h3>
<p>We’ll be looking at environmental variables and a way to search even more deeply into files with the <code>grep</code> command.</p>
</div>
<div style="margin: 5px 5% 10px 5%;"><img src="http://www.sickgaming.net/blog/wp-content/uploads/2018/11/beyond-finding-stuff-with-the-linux-find-command.jpg" width="1497" height="837" title="" alt="" /></div><div><div><img src="http://www.sickgaming.net/blog/wp-content/uploads/2018/11/beyond-finding-stuff-with-the-linux-find-command.jpg" class="ff-og-image-inserted" /></div>
<p>Continuing the quest to become a command-line power user, in this installment, we will be taking on the <code>find</code> command.</p>
<p>Jack Wallen already covered <a href="https://www.linux.com/learn/intro-to-linux/2017/3/how-search-files-linux-command-line">the basics of <code>find</code></a> in an article published recently here on Linux.com. If you are completely unfamiliar with <code>find</code>, please read that article first to come to grips with the essentials.</p>
<p>Done? Good. Now, you need to know that <code>find</code> can be used to do much more than just for search for something, in fact you can use it to search for two or three things. For example:</p>
<pre> find path/to/some/directory/ -type f -iname '*.svg' -o -iname '*.pdf' </pre>
<p>This will cough up all the files with the extensions <code>svg</code> (or <code>SVG</code>) and <code>pdf</code> (or <code>PDF</code>) in the <i>path/to/directory</i> directory. You can add more things to search for using the <code>-o</code> over and over.</p>
<p>You can also search in more than one directory simultaneously just be adding them to the <i>route</i> bit of the command. Say you want to see what is eating up all the space on your hard drive:</p>
<pre> find $HOME /var /etc -size +500M </pre>
<p>This will return all the files bigger than 500 Megabytes (<code>-size +500M</code>) in your home directory, <i>/var</i> and <i>/etc</i>.</p>
<p>Additionally, <code>find</code> also lets you do stuff with the files it… er… finds. For example, you can use the <code>-delete</code> action to remove everything that comes up in a search. Now, be careful with this one. If you run</p>
<pre> # WARNING: DO NOT TRY THIS AT $HOME find . -iname "*" -delete </pre>
<p><code>find</code> will erase everything in the current directory (<code>.</code> is shorthand for “<i>the current directory</i>“) and everything in the subdirectories under it, and then the subdirectories themselves, and then there will be nothing but emptiness and an unbearable feeling that something has gone terribly wrong.</p>
<p>Please do not put it to the test.</p>
<p>Instead, let’s look at some more constructive examples…</p>
<h3>Moving Stuff Around</h3>
<p>Let’s say you have bunch of pictures of Tux the penguin in several formats and spread out over dozens of directories, all under your <i>Documents/</i> folder. You want to bring them all together into one directory (<i>Tux/</i>) to create a gallery you can revel in:</p>
<pre> find $HOME/Documents/ \( -iname "*tux*png" -o -iname "*tux*jpg" -o -iname "*tux*svg" \) -exec cp -v '{}' $HOME/Tux/ \; </pre>
<p>Let’s break this down:</p>
<p>Once you have the basics of modifying files using <code>find</code> under your belt, you will discover all sorts of situations where it comes in handy. For example…</p>
<h3>A Terrible Mish-Mash</h3>
<p>Client X has sent you a zip file with important documents and images for the new website you are working on for them. You copy the zip into your <i>ClientX</i> folder (which already contains dozens of files and directories) and uncompress it with <code>unzip newwebmedia.zip</code> and, gosh darn it, the person who made the zip file didn’t compress the directory itself, but the contents in the directory. Now all the images, text files and subdirectories from the zip are all mixed up with the original contents of you folder, that contains more images, text files, and subdirectories.</p>
<p>You could try and remember what the original files were and then move or delete the ones that came from the zip archive. But with dozens of entries of all kinds, you are bound to get mixed up at some point and forget to move a file, or, worse, delete one of your original files.</p>
<p>Looking at the files’ dates (<code>ls -la *</code>) won’t help either: the Zip program keeps the dates the files were originally created, not when they were zipped or unzipped. This means a “new” file from the zip could very well have a date prior to some of the files that were already in the folder when you did the unzipping.</p>
<p>You probably can guess what comes next: <code>find</code> to the rescue! Move into the directory (<code>cd path/to/ClientX</code>), make a new directory where you want the new stuff to go (<code>mkdir NewStuff</code>), and then try this:</p>
<pre> find . -cnewer newwebmedia.zip -exec mv '{}' NewStuff \; </pre>
<p>Breaking that down:</p>
<ul>
<li>The period (<code>.</code>) tells <code>find</code> to do its thing in the current directory.</li>
<li><code>-cnewer</code> tells <code>find</code> to look for files that have been changed at the same time or after a certain file you give as reference. In this case the reference file is <code>newwebmedia.zip</code>. If you copied the file over at 12:00 and then unpacked it at 12:01, all the files that you unpacked will be tagged as changed at 12:01, that is, after <code>newwebmedia.zip</code> and will match that criteria! And, as long as you didn’t change anything else, they will be the only files meeting that criteria.</li>
<li>The <code>-exec</code> part of the instruction simply tells <code>find</code> to move the files and directories to the <code>NewStuff/</code> directory, thus cleaning up the mess.</li>
</ul>
<p>If you are unsure of anything <code>find</code> may do, you can swap <code>-exec</code> for <code>-ok</code>. The <code>-ok</code> option forces <code>find</code> to check with you before it runs the command you have given it. Accept an action by typing <i>y</i> or reject it with <i>n</i>.</p>
<h3>Next Time</h3>
<p>We’ll be looking at environmental variables and a way to search even more deeply into files with the <code>grep</code> command.</p>
</div>