<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Uuencode on inetshell</title><link>https://inet.sh/en/tags/uuencode/</link><description>Recent content in Uuencode on inetshell</description><generator>Hugo</generator><language>en</language><lastBuildDate>Fri, 13 Nov 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://inet.sh/en/tags/uuencode/index.xml" rel="self" type="application/rss+xml"/><item><title>Copy files over Telnet/SSH with base64 or uuencode</title><link>https://inet.sh/en/posts/linux/copy-files-telnet-ssh-base64-uuencode/</link><pubDate>Fri, 13 Nov 2026 00:00:00 +0000</pubDate><guid>https://inet.sh/en/posts/linux/copy-files-telnet-ssh-base64-uuencode/</guid><description>When all you have is a Telnet or SSH shell with no SCP/SFTP: turn the file into text with base64 or uuencode, paste it on the other side, and restore it. With hash verification.</description><content:encoded><![CDATA[<h2 id="tldr">TL;DR</h2>
<p>With no <code>scp</code>/<code>sftp</code>, turn the binary into ASCII text, push it through the terminal, and rebuild it:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># Source: binary -&gt; text</span>
</span></span><span class="line"><span class="cl">base64 file.bin             <span class="c1"># prints; copy the output</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Destination: text -&gt; binary (paste the block, Ctrl-D ends input)</span>
</span></span><span class="line"><span class="cl">base64 -d &gt; file.bin
</span></span></code></pre></td></tr></table>
</div>
</div><p>Always verify with a hash on both ends (<code>sha256sum file.bin</code>). If it doesn&rsquo;t match, the paste dropped bytes.</p>
<h2 id="when-you-need-this">When you need this</h2>
<p>Sometimes all you have is <strong>a shell</strong>: a Telnet session to an old box, a serial console, an <code>ssh</code> into a jail with no <code>scp</code>, a minimal container with no network tools, or a KVM/IPMI where all you can do is type. No file transfer — but you can <strong>write and read text</strong>.</p>
<p>The trick: any file — even a binary — can be represented as printable ASCII. You encode it at the source, copy the text through the terminal, and decode it at the destination. Two tools do this: <strong>base64</strong> (modern, everywhere) and <strong>uuencode</strong> (classic, from the UUCP and Usenet days).</p>
<h2 id="option-1-base64-recommended">Option 1: base64 (recommended)</h2>
<p><code>base64</code> ships with coreutils, so it&rsquo;s on virtually any modern Linux/BSD/macOS.</p>
<p><strong>At the source</strong> — encode and print the text:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">base64 file.bin
</span></span></code></pre></td></tr></table>
</div>
</div><p>For a large file, send it to a <code>.txt</code> and open it, or print it as a single unwrapped line:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">base64 -w0 file.bin           <span class="c1"># -w0 = no wrap, single line (GNU)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Copy the whole output (it&rsquo;s printable text, safe to paste).</p>
<p><strong>At the destination</strong> — paste the text and decode:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">base64 -d &gt; file.bin
</span></span><span class="line"><span class="cl"><span class="c1"># paste the base64 block here, then Enter and Ctrl-D to close input</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>Ctrl-D</code> signals end of input (EOF) and <code>base64 -d</code> writes the reconstructed binary.</p>
<blockquote>
<p>On macOS/BSD the single-line flag isn&rsquo;t <code>-w0</code>. Use <code>base64 -i file.bin</code> to encode and <code>base64 -D</code> (capital D) to decode. When in doubt, <code>base64 --help</code>.</p></blockquote>
<h2 id="option-2-uuencode--uudecode-classic">Option 2: uuencode / uudecode (classic)</h2>
<p><code>uuencode</code>/<code>uudecode</code> ship in the <strong>sharutils</strong> package. It&rsquo;s what people used to mail binaries over email and Usenet before MIME. Handy on an old system that already has it and lacks base64.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># install if needed</span>
</span></span><span class="line"><span class="cl">sudo apt install sharutils        <span class="c1"># Debian/Ubuntu</span>
</span></span><span class="line"><span class="cl">sudo dnf install sharutils        <span class="c1"># Fedora/RHEL</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>At the source</strong> — the second argument is the name the file will get on decode:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">uuencode file.bin file.bin
</span></span></code></pre></td></tr></table>
</div>
</div><p>It prints a block that starts with <code>begin 644 file.bin</code> and ends with <code>end</code>. Copy <strong>all</strong> of it, including those two lines.</p>
<p><strong>At the destination</strong> — paste the block and decode:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">uudecode &gt; /dev/null
</span></span><span class="line"><span class="cl"><span class="c1"># paste the block (begin ... end), then Ctrl-D</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>uudecode</code> reads the name from the block itself (<code>begin 644 file.bin</code>) and creates <code>file.bin</code> on its own. You don&rsquo;t pass an output name.</p>
<h2 id="always-verify-with-a-hash">Always verify with a hash</h2>
<p>Pasting long text into a terminal is fragile: a truncated buffer, a dropped character, a wrap that injects a space. Confirm the file arrived intact:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># on both ends</span>
</span></span><span class="line"><span class="cl">sha256sum file.bin
</span></span></code></pre></td></tr></table>
</div>
</div><p>If the hashes differ, the paste got corrupted. Retry, or split the file (below).</p>
<h2 id="compress-before-you-encode">Compress before you encode</h2>
<p>base64 <strong>inflates</strong> the file by ~33%. Compress it first and there&rsquo;s less text to paste — and you get to bundle a whole directory into one file. Compress, encode, and on the other side reverse the order: decode, decompress.</p>
<p><strong>A single file</strong> with gzip (or bzip2 / xz, better ratio, slower):</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># source</span>
</span></span><span class="line"><span class="cl">gzip -c file.bin <span class="p">|</span> base64 -w0           <span class="c1"># compress and encode in one go</span>
</span></span><span class="line"><span class="cl"><span class="c1"># bzip2 -c file.bin | base64 -w0        # usually compresses more</span>
</span></span><span class="line"><span class="cl"><span class="c1"># xz   -c file.bin | base64 -w0         # best ratio (slowest)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># destination: decode and decompress</span>
</span></span><span class="line"><span class="cl">base64 -d <span class="p">|</span> gzip -d &gt; file.bin          <span class="c1"># paste the text, Ctrl-D</span>
</span></span><span class="line"><span class="cl"><span class="c1"># base64 -d | bzip2 -d &gt; file.bin</span>
</span></span><span class="line"><span class="cl"><span class="c1"># base64 -d | xz   -d &gt; file.bin</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>A whole directory</strong> with tar (pack + compress + encode):</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># source</span>
</span></span><span class="line"><span class="cl">tar czf - dir/ <span class="p">|</span> base64 -w0             <span class="c1"># c=create z=gzip f=-  -&gt;  to stdout</span>
</span></span><span class="line"><span class="cl"><span class="c1"># tar cjf - dir/  = bzip2 ;  tar cJf - dir/  = xz</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># destination: decode, decompress and extract</span>
</span></span><span class="line"><span class="cl">base64 -d <span class="p">|</span> tar xzf -                    <span class="c1"># paste the text, Ctrl-D</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Verify the <strong>tar.gz</strong> with <code>sha256sum</code> (not the loose contents) on both ends: comparing one file is easier than comparing a directory.</p>
<h2 id="large-files-split-them">Large files: split them</h2>
<p>Pasting megabytes of text into a terminal is asking for trouble. If it&rsquo;s still large after compressing, split before encoding:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># source</span>
</span></span><span class="line"><span class="cl">split -b 100k file.bin part_             <span class="c1"># creates part_aa, part_ab, ...</span>
</span></span><span class="line"><span class="cl">base64 part_aa                            <span class="c1"># ship each part separately</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># destination: rebuild each part and join them</span>
</span></span><span class="line"><span class="cl">cat part_aa part_ab part_ac &gt; file.bin
</span></span><span class="line"><span class="cl">sha256sum file.bin                        <span class="c1"># verify against the source</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="what-each-piece-does">What each piece does</h2>
<table>
  <thead>
      <tr>
          <th>Command</th>
          <th>What it does</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>base64 file</code></td>
          <td>Binary → ASCII text (76-char lines by default)</td>
      </tr>
      <tr>
          <td><code>base64 -w0 file</code></td>
          <td>Same, but a single line (GNU); handy to paste in one go</td>
      </tr>
      <tr>
          <td><code>base64 -d</code></td>
          <td>base64 text → binary (reads stdin until EOF)</td>
      </tr>
      <tr>
          <td><code>uuencode in out</code></td>
          <td>Binary → <code>begin…end</code> block; <code>out</code> = name on decode</td>
      </tr>
      <tr>
          <td><code>uudecode</code></td>
          <td><code>begin…end</code> block → file (takes the name from the block)</td>
      </tr>
      <tr>
          <td><code>gzip -c</code> / <code>-d</code></td>
          <td>Compress / decompress to stdout (also <code>bzip2</code>, <code>xz</code>)</td>
      </tr>
      <tr>
          <td><code>tar czf - dir/</code></td>
          <td>Pack and compress a directory to stdout (<code>z</code>=gzip, <code>j</code>=bzip2, <code>J</code>=xz)</td>
      </tr>
      <tr>
          <td><code>tar xzf -</code></td>
          <td>Extract a directory from stdin</td>
      </tr>
      <tr>
          <td><code>split -b</code></td>
          <td>Chop a file into fixed-size pieces</td>
      </tr>
      <tr>
          <td><code>sha256sum</code></td>
          <td>Hash to verify end-to-end integrity</td>
      </tr>
  </tbody>
</table>
<h2 id="traps">Traps</h2>
<ul>
<li><strong>Always verify with a hash.</strong> It&rsquo;s the only safeguard against a truncated paste. Without it, you think you copied the file and you&rsquo;ve got garbage.</li>
<li><strong>Size grows ~33–35%.</strong> base64 adds ~33%, uuencode ~35%. A 3 MB binary becomes ~4 MB of text to type/paste. That&rsquo;s what <code>split</code> is for.</li>
<li><strong>Different flags on macOS/BSD vs GNU.</strong> <code>-w0</code>/<code>-d</code> are GNU; on macOS it&rsquo;s <code>-i</code>/<code>-D</code>. Don&rsquo;t assume.</li>
<li><strong>Watch your terminal client&rsquo;s auto-wrap.</strong> Some Telnet/serial clients insert breaks or cut long lines. If it fails, use base64 <strong>with</strong> wrap (drop <code>-w0</code>) and smaller blocks.</li>
<li><strong>Telnet is cleartext.</strong> Anything sensitive sent over Telnet travels unencrypted. Use it only on local/serial consoles or trusted networks; for everything else, SSH.</li>
<li><strong>Not for TBs.</strong> This is for rescuing a file when there&rsquo;s no other way, not for moving volumes. If you can use <code>scp</code>/<code>rsync</code>/<code>sftp</code>, use them.</li>
</ul>
<h2 id="see-also">See also</h2>
<ul>
<li><a href="/en/posts/windows/ssh-server-2003-bitvise/">SSH to Windows Server 2003 with Bitvise</a></li>
</ul>
]]></content:encoded></item></channel></rss>