<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bala Krish</title>
    <description>The latest articles on DEV Community by Bala Krish (@balakrish).</description>
    <link>https://dev.to/balakrish</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3852765%2F416d00b2-3020-4f6d-832f-d88e1273c4fe.png</url>
      <title>DEV Community: Bala Krish</title>
      <link>https://dev.to/balakrish</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/balakrish"/>
    <language>en</language>
    <item>
      <title>find is a programming language and nobody uses it</title>
      <dc:creator>Bala Krish</dc:creator>
      <pubDate>Thu, 16 Apr 2026 02:58:17 +0000</pubDate>
      <link>https://dev.to/balakrish/find-is-a-programming-language-and-nobody-uses-it-693</link>
      <guid>https://dev.to/balakrish/find-is-a-programming-language-and-nobody-uses-it-693</guid>
      <description>&lt;p&gt;90% of &lt;code&gt;find&lt;/code&gt; usage looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.log"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which is like using Python only for &lt;code&gt;print("hello")&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The operators nobody uses
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Time-based filtering
&lt;/h3&gt;

&lt;p&gt;Find files modified in the last 30 minutes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find /var/log &lt;span class="nt"&gt;-mmin&lt;/span&gt; &lt;span class="nt"&gt;-30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Files NOT accessed in the last 90 days:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find /home &lt;span class="nt"&gt;-atime&lt;/span&gt; +90
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Files newer than a reference file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find /etc &lt;span class="nt"&gt;-newer&lt;/span&gt; /etc/passwd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last one is wild. "Show me everything in /etc that changed after the last password update." Incredibly useful for incident response - if you know when the breach happened, you can find every file modified after that timestamp.&lt;/p&gt;

&lt;h3&gt;
  
  
  Permission filtering
&lt;/h3&gt;

&lt;p&gt;Find all SUID binaries (a classic security audit):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find / &lt;span class="nt"&gt;-perm&lt;/span&gt; &lt;span class="nt"&gt;-4000&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Files writable by others:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find /var &lt;span class="nt"&gt;-perm&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt;+w &lt;span class="nt"&gt;-type&lt;/span&gt; f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Files with no owner (orphaned after a user deletion):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find / &lt;span class="nt"&gt;-nouser&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-nogroup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Size filtering
&lt;/h3&gt;

&lt;p&gt;Files over 100MB:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find / &lt;span class="nt"&gt;-size&lt;/span&gt; +100M &lt;span class="nt"&gt;-type&lt;/span&gt; f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Empty files (often leftover from crashed processes):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find /tmp &lt;span class="nt"&gt;-empty&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Combining conditions
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;find&lt;/code&gt; supports AND (implicit), OR (&lt;code&gt;-o&lt;/code&gt;), and NOT (&lt;code&gt;!&lt;/code&gt;). With parentheses for grouping.&lt;/p&gt;

&lt;p&gt;"Log files over 10MB that haven't been modified in a week":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find /var/log &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.log"&lt;/span&gt; &lt;span class="nt"&gt;-size&lt;/span&gt; +10M &lt;span class="nt"&gt;-mtime&lt;/span&gt; +7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"Config files that are world-writable OR have no owner":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find /etc &lt;span class="se"&gt;\(&lt;/span&gt; &lt;span class="nt"&gt;-perm&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt;+w &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nt"&gt;-nouser&lt;/span&gt; &lt;span class="se"&gt;\)&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  -exec is where it becomes a language
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;-exec&lt;/code&gt; executes a command on each result. The &lt;code&gt;{}&lt;/code&gt; is replaced with the filename, and &lt;code&gt;\;&lt;/code&gt; terminates the command.&lt;/p&gt;

&lt;p&gt;Delete old temp files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find /tmp &lt;span class="nt"&gt;-mtime&lt;/span&gt; +30 &lt;span class="nt"&gt;-type&lt;/span&gt; f &lt;span class="nt"&gt;-exec&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change ownership of orphaned files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find / &lt;span class="nt"&gt;-nouser&lt;/span&gt; &lt;span class="nt"&gt;-exec&lt;/span&gt; &lt;span class="nb"&gt;chown &lt;/span&gt;root &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the real trick is &lt;code&gt;-exec&lt;/code&gt; with &lt;code&gt;+&lt;/code&gt; instead of &lt;code&gt;\;&lt;/code&gt;. The semicolon variant runs one command per file. The plus variant batches files into a single command invocation, like &lt;code&gt;xargs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find /var/log &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.log"&lt;/span&gt; &lt;span class="nt"&gt;-exec&lt;/span&gt; &lt;span class="nb"&gt;gzip&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt; +
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's one &lt;code&gt;gzip&lt;/code&gt; call with hundreds of arguments, not hundreds of &lt;code&gt;gzip&lt;/code&gt; calls. On a system with 50,000 log files, the difference is minutes vs seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  -delete is the dangerous one
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;find&lt;/code&gt; has a built-in &lt;code&gt;-delete&lt;/code&gt; action. It's faster than &lt;code&gt;-exec rm&lt;/code&gt; because it avoids forking a subprocess for each file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find /tmp &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.cache"&lt;/span&gt; &lt;span class="nt"&gt;-mtime&lt;/span&gt; +7 &lt;span class="nt"&gt;-delete&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The danger: &lt;code&gt;-delete&lt;/code&gt; implies &lt;code&gt;-depth&lt;/code&gt; (processes directories bottom-up). If you put &lt;code&gt;-delete&lt;/code&gt; in the wrong position with other filters, it can delete more than you intended. Always test with &lt;code&gt;-print&lt;/code&gt; first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real incident response example
&lt;/h2&gt;

&lt;p&gt;Server compromised. You know the attacker got in around 14:00 yesterday. Find every file modified since then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; 202604151400 /tmp/marker
find / &lt;span class="nt"&gt;-newer&lt;/span&gt; /tmp/marker &lt;span class="nt"&gt;-not&lt;/span&gt; &lt;span class="nt"&gt;-path&lt;/span&gt; &lt;span class="s2"&gt;"/proc/*"&lt;/span&gt; &lt;span class="nt"&gt;-not&lt;/span&gt; &lt;span class="nt"&gt;-path&lt;/span&gt; &lt;span class="s2"&gt;"/sys/*"&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a reference file with the known breach time. Find everything newer. Exclude virtual filesystems. This gives you a timeline of everything the attacker touched, including backdoors, modified configs, and planted scripts.&lt;/p&gt;

&lt;p&gt;Now pipe it to get details:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find / &lt;span class="nt"&gt;-newer&lt;/span&gt; /tmp/marker &lt;span class="nt"&gt;-not&lt;/span&gt; &lt;span class="nt"&gt;-path&lt;/span&gt; &lt;span class="s2"&gt;"/proc/*"&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f &lt;span class="nt"&gt;-exec&lt;/span&gt; &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt; +
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full permissions, ownership, and timestamps for every modified file. Ten seconds to run. Manual inspection of each directory would take hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this isn't taught well
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;find&lt;/code&gt; has terrible man page ergonomics. The options are dense, the interaction between operators is non-obvious, and the difference between &lt;code&gt;-exec {} \;&lt;/code&gt; and &lt;code&gt;-exec {} +&lt;/code&gt; is buried in a paragraph that reads like a POSIX spec.&lt;/p&gt;

&lt;p&gt;Most people learn &lt;code&gt;find . -name "pattern"&lt;/code&gt; and stop there because the next level of the man page is intimidating. Understandable. But the difference between "I can find files by name" and "I can audit an entire filesystem in one command" is about two hours of practice with the operators above.&lt;/p&gt;

&lt;p&gt;Several of the &lt;a href="https://sudorank.com/track/linux-survival-guide" rel="noopener noreferrer"&gt;Linux challenges on SudoRank&lt;/a&gt; use &lt;code&gt;find&lt;/code&gt; as the primary tool. Not because find is the only way, but because it's usually the fastest.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>bash</category>
      <category>tutorial</category>
      <category>devops</category>
    </item>
    <item>
      <title>I got my React SPA to 95/100/100/100 on mobile PageSpeed</title>
      <dc:creator>Bala Krish</dc:creator>
      <pubDate>Tue, 31 Mar 2026 05:54:31 +0000</pubDate>
      <link>https://dev.to/balakrish/i-got-my-react-spa-to-95100100100-on-mobile-pagespeed-1mb5</link>
      <guid>https://dev.to/balakrish/i-got-my-react-spa-to-95100100100-on-mobile-pagespeed-1mb5</guid>
      <description>&lt;p&gt;81/93/92/92 → 95/100/100/100. Mobile, simulated slow 4G. Here's everything I did, including the stuff that backfired.&lt;/p&gt;

&lt;p&gt;The site is &lt;a href="https://sudorank.com" rel="noopener noreferrer"&gt;SudoRank&lt;/a&gt; - React 19, TanStack Router, Tailwind 4, running on Cloudflare Pages with 523 prerendered pages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pagespeed.web.dev/analysis/https-sudorank-com/zdhzhd6bag?form_factor=mobile" rel="noopener noreferrer"&gt;Before: 81/93/92/92&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fssj1f3ldujsrtn9ym38x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fssj1f3ldujsrtn9ym38x.png" alt="PageSpeed before - 81/93/92/92" width="800" height="331"&gt;&lt;/a&gt; - single 313 KiB gzip bundle, zero code splitting, Google Fonts from CDN, Clarity and GA loading eagerly. Basically every mistake you can make.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fonts
&lt;/h2&gt;

&lt;p&gt;Google Fonts means three origin connections on slow 4G. Tried @fontsource-variable packages first - score tanked 81 → 67, fonts got bundled into JS. Downloaded the .woff2 files instead, &lt;code&gt;@font-face&lt;/code&gt; with &lt;code&gt;font-display: swap&lt;/code&gt; in &lt;code&gt;public/fonts/&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Analytics
&lt;/h2&gt;

&lt;p&gt;Wrapped Clarity + GA in a &lt;code&gt;setTimeout(fn, 3500)&lt;/code&gt;. Page is rendered by then. GA still picks up the pageview, Clarity replays from initialization.&lt;/p&gt;

&lt;p&gt;Also tried font preloads here - score went 77 → 74. Preloads fought the JS bundle for bandwidth on 1.6 Mbps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code splitting
&lt;/h2&gt;

&lt;p&gt;TanStack Router has built-in code splitting. I hadn't turned it on. 22 routes in one 313 KiB bundle, including xterm.js (342KB raw).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nc"&gt;TanStackRouterVite&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;autoCodeSplitting&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Homepage JS went from 313 KiB to ~164 KiB gzip. FCP 3.0s → 2.1s, LCP 3.9s → 2.6s. This was the entire Performance improvement.&lt;/p&gt;

&lt;h2&gt;
  
  
  The other three scores
&lt;/h2&gt;

&lt;p&gt;SEO: Cloudflare was injecting non-standard directives into robots.txt. Wrote my own. 92 → 100.&lt;/p&gt;

&lt;p&gt;Best Practices: Four CSP violations from analytics domains I hadn't whitelisted. Added them. 92 → 100.&lt;/p&gt;

&lt;p&gt;Accessibility took two rounds. First was a low-contrast text color and a heading skip (h1 jumped to h3). That got it from 93 to 95. The second one was harder - a purple label on a card with a semi-transparent purple background. The contrast checker said it was fine because I was testing against the base dark bg, not the composited result. Compositing &lt;code&gt;rgba(139,92,246,0.06)&lt;/code&gt; onto #13131A gives something like #1A1727, and the contrast dropped to 4.14:1. Changed to a lighter purple. 95 → 100.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it ended up
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://pagespeed.web.dev/analysis/https-sudorank-com/rvhzq7qlwy?form_factor=mobile" rel="noopener noreferrer"&gt;After: 95/100/100/100&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnz5wz94vftdqttxejtmv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnz5wz94vftdqttxejtmv.png" alt="PageSpeed after - 95/100/100/100" width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;FCP&lt;/td&gt;
&lt;td&gt;3.0s&lt;/td&gt;
&lt;td&gt;2.0s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LCP&lt;/td&gt;
&lt;td&gt;3.9s&lt;/td&gt;
&lt;td&gt;2.6s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TBT&lt;/td&gt;
&lt;td&gt;30ms&lt;/td&gt;
&lt;td&gt;0ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speed Index&lt;/td&gt;
&lt;td&gt;3.0s&lt;/td&gt;
&lt;td&gt;2.0s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Getting to 100 would mean inlining critical CSS and shrinking React core under 80KB. Google ranks on Core Web Vitals, not Lighthouse scores. All CWV are green.&lt;/p&gt;

&lt;p&gt;I grew up in Trichy with dial-up. Pages rendered one line at a time. PageSpeed's simulated slow 4G isn't far off. We used to just wait. Now a 3-second load and people think your site is broken.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;&lt;a href="https://sudorank.com" rel="noopener noreferrer"&gt;SudoRank&lt;/a&gt; if you want to run PageSpeed on it yourself.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>performance</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
