bash-hackers-wiki/howto/pax/index.html

71 lines
66 KiB
HTML
Raw Permalink Normal View History

<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><link href=https://flokoe.github.io/bash-hackers-wiki/howto/pax/ rel=canonical><link href=../mutex/ rel=prev><link href=../redirection_tutorial/ rel=next><link rel=icon href=../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.5.44"><title>pax - the POSIX archiver - The Bash Hackers Wiki</title><link rel=stylesheet href=../../assets/stylesheets/main.0253249f.min.css><link rel=stylesheet href=../../assets/stylesheets/palette.06af60db.min.css><link rel=preconnect href=https://fonts.gstatic.com crossorigin><link rel=stylesheet href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback"><style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style><script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script></head> <body dir=ltr data-md-color-scheme=default data-md-color-primary=indigo data-md-color-accent=indigo> <input class=md-toggle data-md-toggle=drawer type=checkbox id=__drawer autocomplete=off> <input class=md-toggle data-md-toggle=search type=checkbox id=__search autocomplete=off> <label class=md-overlay for=__drawer></label> <div data-md-component=skip> <a href=#pax-the-posix-archiver class=md-skip> Skip to content </a> </div> <div data-md-component=announce> </div> <header class=md-header data-md-component=header> <nav class="md-header__inner md-grid" aria-label=Header> <a href=../.. title="The Bash Hackers Wiki" class="md-header__button md-logo" aria-label="The Bash Hackers Wiki" data-md-component=logo> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg> </a> <label class="md-header__button md-icon" for=__drawer> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg> </label> <div class=md-header__title data-md-component=header-title> <div class=md-header__ellipsis> <div class=md-header__topic> <span class=md-ellipsis> The Bash Hackers Wiki </span> </div> <div class=md-header__topic data-md-component=header-topic> <span class=md-ellipsis> pax - the POSIX archiver </span> </div> </div> </div> <form class=md-header__option data-md-component=palette> <input class=md-option data-md-color-media data-md-color-scheme=default data-md-color-primary=indigo data-md-color-accent=indigo aria-label="Switch to dark mode" type=radio name=__palette id=__palette_0> <label class="md-header__button md-icon" title="Switch to dark mode" for=__palette_1 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> <input class=md-option data-md-color-media data-md-color-scheme=slate data-md-color-primary=indigo data-md-color-accent=indigo aria-label="Switch to light mode" type=radio name=__palette id=__palette_1> <label class="md-header__button md-icon" title="Switch to light mode" for=__palette_0 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> </form> <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(
pax -r &lt;myarchive.tar &#39;data/sales/year_200[135].txt&#39;
# should be equivalent to
pax -r &lt;myarchive.tar &#39;data/sales/year_2001.txt&#39; &#39;data/sales/year_2003.txt&#39; &#39;data/sales/year_2005.txt&#39;
</code></pre></div> <h2 id=using-pax>Using pax<a class=headerlink href=#using-pax title="Permanent link">&para;</a></h2> <p>This is a brief description of using <code>pax</code> as a normal archiver system, like you would use <code>tar</code>.</p> <h3 id=creating-an-archive>Creating an archive<a class=headerlink href=#creating-an-archive title="Permanent link">&para;</a></h3> <p>This task is done with basic syntax</p> <div class=highlight><pre><span></span><code># archive contents to stdout
pax -w &gt;archive.tar README.txt *.png data/
# equivalent, extract archive contents directly to a file
pax -w -x ustar -f archive.tar README.txt *.png data/
</code></pre></div> <p><code>pax</code> is in <em>write</em> mode, the given filenames are packed into an archive:</p> <ul> <li><code>README.txt</code> is a normal file, it will be packed</li> <li><code>*.png</code> is a pathname glob <strong>for your shell</strong>, the shell will substitute all matching filenames <strong>before</strong> <code>pax</code> is executed. The result is a list of filenames that will be packed like the <code>README.txt</code> example above</li> <li><code>data/</code> is a directory. <strong>Everything</strong> in this directory will be packed into the archive, i.e. not just an empty directory</li> </ul> <p>When you specify the <code>-v</code> option, <code>pax</code> will write the pathnames of the files inserted into the archive to <code>STDERR</code>.</p> <p>When, and only when, no filename arguments are specified, <code>pax</code> attempts to read filenames from <code>STDIN</code>, separated by newlines. This way you can easily combine <code>find</code> with <code>pax</code>:</p> <div class=highlight><pre><span></span><code>find . -name &#39;*.txt&#39; | pax -wf textfiles.tar -x ustar
</code></pre></div> <h3 id=listing-archive-contents>Listing archive contents<a class=headerlink href=#listing-archive-contents title="Permanent link">&para;</a></h3> <p>The standard output format to list archive members simply is to print each filename to a separate line. But the output format can be customized to include permissions, timestamps, etc. with the <code>-o listopt=&lt;FORMAT&gt;</code> specification. The syntax of the format specification is strongly derived from the <code>printf(3)</code> format specification.</p> <p><strong>Unfortunately</strong> the <code>pax</code> utility delivered with Debian doesn't seem to support these extended listing formats.</p> <p>However, <code>pax</code> lists archive members in a <code>ls -l</code>-like format, when you give the <code>-v</code> option:</p> <div class=highlight><pre><span></span><code>pax -v &lt;myarchive.tar
# or, of course
pax -vf myarchive.tar
</code></pre></div> <h3 id=extracting-from-an-archive>Extracting from an archive<a class=headerlink href=#extracting-from-an-archive title="Permanent link">&para;</a></h3> <p>You can extract all files, or files (not) matching specific patterns from an archive using constructs like:</p> <div class=highlight><pre><span></span><code># &quot;normal&quot; extraction
pax -rf myarchive.tar &#39;*.txt&#39;
# with inverted pattern
pax -rf myarchive.tar -c &#39;*.txt&#39;
</code></pre></div> <h3 id=copying-files>Copying files<a class=headerlink href=#copying-files title="Permanent link">&para;</a></h3> <p>To copy directory contents to another directory, similar to a <code>cp -a</code> command, use:</p> <div class=highlight><pre><span></span><code>mkdir destdir
pax -rw dir destdir #creates a copy of dir in destdir/, i.e. destdir/dir
</code></pre></div> <h3 id=copying-files-via-ssh>Copying files via ssh<a class=headerlink href=#copying-files-via-ssh title="Permanent link">&para;</a></h3> <p>To copy directory contents to another directory on a remote system, use:</p> <div class=highlight><pre><span></span><code>pax -w localdir | ssh user@host &quot;cd distantdest &amp;&amp; pax -r -v&quot;
pax -w localdir | gzip | ssh user@host &quot;cd distantdir &amp;&amp; gunzip | pax -r -v&quot; #compress the sent data
</code></pre></div> <p>These commands create a copy of localdir in distandir (distantdir/dir) on the remote machine.</p> <h2 id=advanced-usage>Advanced usage<a class=headerlink href=#advanced-usage title="Permanent link">&para;</a></h2> <h3 id=backup-your-daily-work>Backup your daily work<a class=headerlink href=#backup-your-daily-work title="Permanent link">&para;</a></h3> <p><u><strong>Note:</strong></u> <code>-T</code> is an extension and is not defined by POSIX.</p> <p>Say you have write-access to a fileserver mounted on your filesystem tree. In <em>copy</em> mode, you can tell <code>pax</code> to copy only files that were modified today:</p> <div class=highlight><pre><span></span><code>mkdir /n/mybackups/$(date +%A)/
pax -rw -T 0000 data/ /n/mybackups/$(date +%A)/
</code></pre></div> <p>This is done using the <code>-T</code> switch, which normally allows you to specify a time window, but in this case, only the start time which means "today at midnight".</p> <p>When you execute this "very simple backup" after your daily work, you will have a copy of the modified files.</p> <p><u><strong>Note:</strong></u> The <code>%A</code> format from <code>date</code> expands to the name of the current day, localized, e.g. "Friday" (en) or "Mittwoch" (de).</p> <p>The same, but with an archive, can be accomplished by:</p> <div class=highlight><pre><span></span><code>pax -w -T 0000 -f /n/mybackups/$(date +%A)
</code></pre></div> <p>In this case, the day-name is an archive-file (you don't need a filename extension like <code>.tar</code> but you can add one, if desired).</p> <h3 id=changing-filenames-while-archiving>Changing filenames while archiving<a class=headerlink href=#changing-filenames-while-archiving title="Permanent link">&para;</a></h3> <p><code>pax</code> is able to rewrite filenames while archiving or while extracting from an archive. This example creates a tar archive containing the <code>holiday_2007/</code> directory, but the directory name inside the archive will be <code>holiday_pics/</code>:</p> <div class=highlight><pre><span></span><code>pax -x ustar -w -f holiday_pictures.tar -s &#39;/^holiday_2007/holiday_pics/&#39; holiday_2007/
</code></pre></div> <p>The option responsible for the string manipulation is the <code>-s &lt;REWRITE-SPECIFICATION&gt;</code>. It takes the string rewrite specification as an argument, in the form <code>/OLD/NEW/[gp]</code>, which is an <code>ed(1)</code>-like regular expression (BRE) for <code>old</code> and generally can be used like the popular sed construct <code>s/from/to/</code>. Any non-null character can be used as a delimiter, so to mangle pathnames (containing slashes), you could use <code>#/old/path#/new/path#</code>.</p> <p>The optional <code>g</code> and <code>p</code> flags are used to apply substitution <strong>(g)</strong>lobally to the line or to <strong>(p)</strong>rint the original and rewritten strings to <code>STDERR</code>.</p> <p>Multiple <code>-s</code> options can be specified on the command line. They are applied to the pathname strings of the files or archive members. This happens in the order they are specified.</p> <h3 id=excluding-files-from-an-archive>Excluding files from an archive<a class=headerlink href=#excluding-files-from-an-archive title="Permanent link">&para;</a></h3> <p>The -s command seen above can be used to exclude a file. The substitution must result in a null string: For example, let's say that you want to exclude all the CVS directories to create a source code archive. We are going to replace the names containing /CVS/ with nothing, note the <code>.*</code> they are needed because we need to match the entire pathname.</p> <div class=highlight><pre><span></span><code> pax -w -x ustar -f release.tar -s&#39;,.*/CVS/.*,,&#39; myapplication
</code></pre></div> <p>You can use several -s options, for instance, let's say you also want to remove files ending in <code>~</code>:</p> <div class=highlight><pre><span></span><code> pax -w -x ustar -f release.tar -&#39;s,.*/CVS/.*,,&#39; -&#39;s/.*~//&#39; myapplication
</code></pre></div> <p>This can also be done while reading an archive, for instance, suppose you have an archive containing a "usr" and a "etc" directory but that you want to extract only the "usr" directory:</p> <div class=highlight><pre><span></span><code>pax -r -f archive.tar -s&#39;,^etc/.*,,&#39; #the etc/ dir is not extracted
</code></pre></div> <h3 id=getting-archive-filenames-from-stdin>Getting archive filenames from STDIN<a class=headerlink href=#getting-archive-filenames-from-stdin title="Permanent link">&para;</a></h3> <p>Like <code>cpio</code>, pax can read filenames from standard input (<code>stdin</code>). This provides great flexibility - for example, a <code>find(1)</code> command may select files/directories in ways pax can't do itself. In <strong>write</strong> mode (creating an archive) or <strong>copy</strong> mode, when no filenames are given, pax expects to read filenames from standard input. For example:</p> <div class=highlight><pre><span></span><code># Back up config files changed less than 3 days ago
find /etc -type f -mtime -3 | pax -x ustar -w -f /backups/etc.tar
# Copy only the directories, not the files
mkdir /target
find . -type d -print | pax -r -w -d /target
# Back up anything that changed since the last backup
find . -newer /var/run/mylastbackup -print0 |
pax -0 -x ustar -w -d -f /backups/mybackup.tar
touch /var/run/mylastbackup
</code></pre></div> <p>The <code>-d</code> option tells pax <code>not</code> to recurse into directories it reads (<code>cpio</code>-style). Without <code>-d</code>, pax recurses into all directories (<code>tar</code>-style).</p> <p><strong>Note</strong>: the <code>-0</code> option is not standard, but is present in some implementations.</p> <h2 id=from-tar-to-pax>From tar to pax<a class=headerlink href=#from-tar-to-pax title="Permanent link">&para;</a></h2> <p><code>pax</code> can handle the <code>tar</code> archive format, if you want to switch to the standard tool an alias like:</p> <div class=highlight><pre><span></span><code>alias tar=&#39;echo USE PAX, idiot. pax is the standard archiver!; # &#39;
</code></pre></div> <p>in your <code>~/.bashrc</code> can be useful :-D.</p> <p>Here is a quick table comparing (GNU) <code>tar</code> and <code>pax</code> to help you to make the switch:</p> <table> <thead> <tr> <th>TAR</th> <th>PAX</th> <th>Notes</th> </tr> </thead> <tbody> <tr> <td><code>tar xzvf file.tar.gz</code></td> <td><code>pax -rvz -f file.tar.gz</code></td> <td><code>-z</code> is an extension, POSIXly: <code>gunzip &lt;file.tar.gz | pax -rv</code></td> </tr> <tr> <td><code>tar czvf archive.tar.gz path ...</code></td> <td><code>pax -wvz -f archive.tar.gz path ...</code></td> <td><code>-z</code> is an extension, POSIXly: <code>pax -wv path | gzip &gt; archive.tar.gz</code></td> </tr> <tr> <td><code>tar xjvf file.tar.bz2</code></td> <td><code>bunzip2 &lt;file.tar.bz2 | pax -rv</code></td> <td></td> </tr> <tr> <td><code>tar cjvf archive.tar.bz2 path ...</code></td> <td><code>pax -wv path | bzip2 &gt; archive.tar.bz2</code></td> <td></td> </tr> <tr> <td><code>tar tzvf file.tar.gz</code></td> <td><code>pax -vz -f file.tar.gz</code></td> <td><code>-z</code> is an extension, POSIXly: <code>gunzip &lt;file.tar.gz | pax -v</code></td> </tr> </tbody> </table> <p><code>pax</code> might not create ustar (<code>tar</code>) archives by default but its own pax format, add <code>-x ustar</code> if you want to ensure pax creates tar archives!</p> <h2 id=implementations>Implementations<a class=headerlink href=#implementations title="Permanent link">&para;</a></h2> <ul> <li><a href=http://www2.research.att.com/sw/download/ >AT&amp;T AST toolkit</a> | <a href=http://www2.research.att.com/~gsf/man/man1/pax.html>manpage</a></li> <li><a href=http://heirloom.sourceforge.net/index.html>Heirloom toolchest</a> | <a href=http://heirloom.sourceforge.net/man/pax.1.html>manpage</a></li> <li><a href=http://www.openbsd.org/cgi-bin/cvsweb/src/bin/pax/ >OpenBSD pax</a> | <a href="http://www.openbsd.org/cgi-bin/man.cgi?query=pax&apropos=0&sektion=0&manpath=OpenBSD+Current&arch=i386&format=html">manpage</a></li> <li><a href=https://launchpad.net/paxmirabilis>MirBSD pax</a> | <a href=https://www.mirbsd.org/htman/i386/man1/pax.htm>manpage</a> - Debian bases their package upon this.</li> <li><a href=http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html>SUS pax specification</a></li> </ul> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">November 13, 2024</span> </span> <span class=md-source-file__fact> <span class=md-icon title=Created> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M14.47 15.08 11 13V7h1.5v5.25l3.08 1.83c-.41.28-.79.62-1.11 1m-1.39 4.84c-.36.05-.71.08-1.08.08-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8c0 .37-.03.72-.08 1.08.69.1 1.33.32 1.92.64.1-.56.16-1.13.16-1.72 0-5.5-4.5-10-10-10S2 6.5 2 12s4.47 10 10 10c.59 0 1.16-.06 1.72-.16-.32-.59-.54-1.23-.64-1.92M18 15v3h-3v2h3v3h2v-3h3v-2h-3v-3z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">November 13, 2024</span> </span> </aside> <h2 id=__comments>Comments</h2> <script src=https://giscus.app/client.js data-repo=flokoe/bash-hackers-wiki data-repo-id=R_kgDOJ3Nr6Q data-category="Giscus Page Comments" data-category-id=DIC_kwDOJ3Nr6c4CXq9t data-mapping=pathname data-strict=1 data-reactions-enabled=1 data-emit-metadata=0 data-input-position=top data-theme=preferred_color_scheme data-lang=en data-loading=lazy crossorigin=anonymous async>
</script> <script>
var giscus = document.querySelector("script[src*=giscus]")
/* Set palette on initial load */
var palette = __md_get("__palette")
if (palette && typeof palette.color === "object") {
var theme = palette.color.scheme === "slate" ? "dark" : "light"
giscus.setAttribute("data-theme", theme)
}
/* Register event handlers after documented loaded */
document.addEventListener("DOMContentLoaded", function() {
var ref = document.querySelector("[data-md-component=palette]")
ref.addEventListener("change", function() {
var palette = __md_get("__palette")
if (palette && typeof palette.color === "object") {
var theme = palette.color.scheme === "slate" ? "dark" : "light"
/* Instruct Giscus to change theme */
var frame = document.querySelector(".giscus-frame")
frame.contentWindow.postMessage(
{ giscus: { setConfig: { theme } } },
"https://giscus.app"
)
}
})
})
</script> </article> </div> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> Made with <a href=https://squidfunk.github.io/mkdocs-material/ target=_blank rel=noopener> Material for MkDocs </a> </div> </div> </div> </footer> </div> <div class=md-dialog data-md-component=dialog> <div class="md-dialog__inner md-typeset"></div> </div> <script id=__config type=application/json>{"base": "../..", "features": ["navigation.instant", "navigation.tracking", "navigation.tabs", "navigation.sections", "navigation.top", "content.action.view", "content.action.edit", "search.suggest", "search.highlight", "content.code.copy"], "search": "../../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script> <script src=../../assets/javascripts/bundle.83f73b43.min.js></script> </body> </html>