AR(1)

πŸ“¦ version 2.45, in ubuntu questing

πŸŽ€ AR(1) Β· GNU Development Tools πŸŽ€

✨ NAME ✨

ar - create, modify, and extract from archives πŸ’–

🧚 SYNOPSIS 🧚

ar [-X32_64] [-]p[mod] [--plugin name] [--target bfdname] [--output dirname] [--record-libdeps libdeps] [--thin] [relpos] [count] archive [member...]

πŸ“š DESCRIPTION πŸ“š

okay so the GNU ar program is the one that creates, modifies, and extracts from archives πŸ¦‹ An archive is a single file that holds a whole collection of other files, stored in a way that lets you pull the original individual files back out. Those files are called members of the archive. It's giving organized folder energy, but make it a single file πŸ’…

The original files' contents, mode (permissions), timestamp, owner, and group all get saved inside the archive, and they can be restored when you extract. Your files come back looking exactly like they went in ✨

GNU ar can keep archives whose members have names of any length 🌈 BUT, depending on how ar was configured on your system, there might be a limit on member-name length so it plays nicely with archive formats made by other tools πŸ™ˆ If there is a limit, it's often 15 characters (typical of formats related to a.out) or 16 characters (typical of formats related to coff). Lowkey annoying, but that's the deal.

ar is considered a binary utility πŸ”₯ because archives like this are mostly used as libraries that hold commonly needed subroutines. Libraries often depend on other libraries, so ar can also record a library's dependencies when you specify the --record-libdeps option 🫢

ar builds an index of the symbols defined in relocatable object modules inside the archive when you specify the modifier s πŸ’– Once it exists, that index gets updated in the archive whenever ar changes its contents (except for the q update operation, which we'll get to). An archive with an index speeds up linking to the library, and lets routines in the library call each other no matter where they sit in the archive. Iconic behaviour, honestly ✨

You can use nm -s or nm --print-armap to list this index table πŸ‘€ If an archive doesn't have the table, another program called ranlib can be used to add just the table.

ar can also make a thin archive πŸ¦‹ A thin archive holds a symbol index plus references to the original copies of the member files, instead of copies of the files themselves. This is super useful for building libraries for a local build tree, where the relocatable objects are expected to stick around anyway. Copying the contents of every object would only waste time and space, so thin archives just point at them instead πŸ’…

An archive is either thin or normal, never both at the same time πŸ™…β€β™€οΈ Once an archive is created, its format can't be changed without deleting it first and then creating a new archive in its place. No take-backs, bestie.

Thin archives also get flattened 🧚 So if you add one thin archive to another thin archive, it doesn't nest inside it like it would with a normal archive. Instead, the elements of the first archive get added individually to the second archive. Clean and tidy, no cap.

The paths to the elements of a thin archive are stored relative to the archive itself 🌸

ar is designed to be compatible with two different facilities πŸ‘‘ You can control it with command-line options, like the different versions of ar on Unix systems. Or, if you specify the single command-line option -M, you can control it with a script supplied through standard input, like the MRI "librarian" program. Two ways to slay, pick your fave ✨


πŸ’– OPTIONS πŸ’–

okay, the options part is where the magic happens πŸͺ„ ar lets you mix the operation code p and the modifier flags mod in any order, as long as they're inside the first command-line argument.

If you want, you can even begin that first command-line argument with a dash πŸŽ€

The p keyletter is the operation to run. It can be any of the operations below, but you have to pick only one of them πŸ™ˆ

🌸 Operations 🌸

  • d β€” Delete members from the archive πŸ—‘οΈ Name the members you want gone as member.... If you don't specify any files to delete, the archive is left totally untouched.
    • If you add the v modifier, ar lists each member as it gets deleted.
  • m β€” Move members around inside an archive πŸ¦‹
    • The order of members can make a real difference in how programs get linked against the library, especially if a symbol is defined in more than one member. So this one matters, bestie.
    • If you don't use any modifiers with m, any members you name in the member arguments get moved to the end of the archive. If you want them somewhere specific instead, use the a, b, or i modifiers.
  • p β€” Print the specified members of the archive to the standard output file πŸ“€
    • If you add the v modifier, the member name gets shown before its contents are copied to standard output.
    • If you don't name any member arguments, all the files in the archive get printed.
  • q β€” Quick append πŸƒβ€β™€οΈπŸ’¨ Historically, this adds the files member... to the end of the archive, without checking for replacement.
    • The a, b, and i modifiers don't affect this operation. New members always go at the end of the archive, no exceptions.
    • The v modifier makes ar list each file as it gets appended.
    • Since the whole point of this operation is speed, implementations of ar are allowed to skip updating the archive's symbol table if one exists. But too many systems just assume symbol tables are always up-to-date, so GNU ar rebuilds the table even with a quick append. Safe choice, honestly.
    • > Note - GNU ar treats the command qs as a synonym for r, meaning it replaces files that already exist in the archive and appends new ones at the end. Double check which one you meant, babe πŸ’…
  • r β€” Insert the files member... into the archive, with replacement πŸ’– This differs from q because any previously existing members get deleted if their names match the ones being added.
    • If one of the files named in member... doesn't exist, ar shows an error message and leaves any existing members matching that name undisturbed. Not a total loss, phew 😭
    • By default, new members get added at the end of the file. But you can use one of the modifiers a, b, or i to place them relative to some existing member.
    • The v modifier used with this operation gives you a line of output for each file inserted, along with one of the letters a or r. a means the file was appended (no old member got deleted), and r means it replaced an old one.
  • s β€” Add an index to the archive, or update it if it already exists πŸ”₯ This one is a bit of a rule-breaker: there can normally only be one command letter, but s can be used as either a command or a modifier. Either way, it does the same thing ✨
  • t β€” Display a table listing the contents of the archive, or just the files named in member... that are present in the archive πŸ“‹
    • Normally only the member name shows up. If you specify the O modifier, the corresponding offset of the member is displayed too.
    • To see the modes (permissions), timestamp, owner, group, and size, include the v modifier.
    • If you don't specify a member, every file in the archive gets listed.
    • Quick heads-up: if there's more than one file with the same name (say, fie) in an archive (say, b.a), then ar t b.a fie only lists the first instance πŸ™ˆ To see all of them, you have to ask for a complete listing, which in our example would be ar t b.a.
  • x β€” Extract members (named member) from the archive πŸ“¦ You can use the v modifier with this operation to make ar list each name as it's extracted.
    • If you don't specify a member, every file in the archive gets extracted.
    • Files can't be extracted from a thin archive. There are also restrictions when extracting from archives created with P: the paths must not be absolute, they may not contain .., and any subdirectories in the paths must already exist. If you want to dodge these restrictions, use the --output option to specify an output directory instead 🫢

πŸ’… Modifiers πŸ’…

A bunch of modifiers (mod) can come right after the p keyletter to tweak how an operation behaves ✨

  • a β€” Add new files after an existing member of the archive πŸŽ€ If you use a, the name of an existing archive member has to be given as the relpos argument, placed before the archive specification.
  • b β€” Add new files before an existing member of the archive πŸŽ€ If you use b, the name of an existing archive member has to be given as the relpos argument, placed before the archive specification. (Same as i.)
  • c β€” Create the archive 🌱 The specified archive is always created if it didn't exist when you request an update. But ar issues a warning unless you say in advance that you expect to create it, which is what this modifier does.
  • D β€” Operate in deterministic mode 🧚 When adding files and the archive index, this uses zero for UIDs, GIDs, and timestamps, and uses consistent file modes for all files. With this on, running ar with identical options and identical input files gives identical output files every time, no matter the input files' owners, groups, file modes, or modification times. So reproducible, very clean.
    • If binutils was configured with --enable-deterministic-archives, this mode is on by default. You can turn it off with the U modifier, which is described below.
  • f β€” Truncate names in the archive βœ‚οΈ ar normally allows file names of any length. That can make archives that aren't compatible with the native ar program on some systems. If that's a concern for you, the f modifier truncates file names when they go into the archive.
  • i β€” Insert new files before an existing member of the archive πŸŽ€ If you use i, the name of an existing archive member has to be given as the relpos argument, placed before the archive specification. (Same as b.)
  • l β€” Specify dependencies of this library πŸ”— The dependencies must come immediately after this option character, must use the same syntax as the linker command line, and must be inside a single argument. So if you need multiple items, you have to quote them so they form one command-line argument. For example:
l "-L/usr/local/lib -lmydep1 -lmydep2"
  • N β€” Uses the count parameter πŸ”’ This is for when there are multiple entries in the archive with the same name. It extracts or deletes instance count of the given name from the archive.
  • o β€” Preserve the original dates of members when extracting them πŸ•°οΈ If you don't specify this modifier, files extracted from the archive get stamped with the time of extraction instead.
  • O β€” Display member offsets inside the archive πŸ‘€ Use this together with the t operation.
  • P β€” okay bestie, this one is all about full path names πŸ›£οΈ P tells ar to use the whole path when it matches or stores names in the archive. Heads up though: archives made with full path names aren't POSIX compliant, so they might not play nice with anything except up-to-date GNU tools πŸ’€. If you modify one with GNU ar without P, the full path names get stripped, unless it's a thin archive. P is also useful when you add files to a thin archive, because r without P ignores the path when picking which element to replace. Like, watch this:
ar rcST archive.a subdir/file1 subdir/file2 file1

This will replace the first "subdir/file1" with "file1" from the current directory 😭. Add P and that replacement gets prevented πŸ™…β€β™€οΈ.

  • s β€” writes an object-file index into the archive, or updates an existing one, even if nothing else changed ✨. You can use it with any operation or all on its own. Running ar s on an archive is the same as running ranlib on it 🧚.
  • S β€” no archive symbol table gets generated 🫢. This can speed up building a big library in several steps. The catch is that the resulting archive can't be used with the linker 🚫. To get a symbol table, leave off S on the last ar run, or just run ranlib on the archive.
  • T β€” deprecated alias for --thin πŸ™ˆ. Don't use it, bestie, because in lots of ar implementations T means something totally different, as defined by the X/Open System Interface.
  • u β€” okay so normally ar r... inserts every file you list πŸ’…. With u, only the files that are newer than the existing members with the same names get inserted. u is only allowed with the r (replace) operation. And qu is a big no, because checking the timestamps would cancel out the speed boost from q πŸ’€.
Note: if an archive was created in a deterministic way, e.g. with the D modifier, then replacement will always happen and u won't do anything πŸ™ƒ.
  • U β€” not deterministic mode 🌸. This is the inverse of D: added files and the archive index get their actual UID, GID, timestamp, and file mode values. This is the default unless binutils was configured with --enable-deterministic-archives.
  • v β€” verbose mode, the main character version of an operation πŸ¦‹. Lots of operations will show extra info, like the filenames they processed, when you add v.
  • V β€” shows the version number of ar πŸ”₯.

The ar program also has some command-line options that aren't modifiers or actions, but they still change how it behaves in specific ways πŸŽ€:

  • --help β€” shows the list of command-line options ar supports, then exits πŸ“œ.
  • --version β€” shows ar's version information, then exits 🌈.
  • -X32_64 β€” ar ignores an initial option spelled -X32_64, for AIX compatibility πŸ“. The behaviour this option produces is already the default for GNU ar. ar doesn't support any of the other -X options, and in particular it doesn't support -X32, which is the default for AIX ar 😀.
  • --plugin name β€” this optional switch makes ar load the plugin called name, which adds support for more file formats, including object files with link-time optimization information πŸ§šβ€β™€οΈ. This option is only available if the toolchain was built with plugin support enabled. If you don't give --plugin but plugin support is enabled, ar goes through the files in ${libdir}/bfd-plugins in alphabetic order, and the first plugin that claims the object in question gets used πŸ”.

Please note, this plugin search directory is not the one used by ld's -plugin option πŸ‘€. To make ar use the linker plugin, it has to be copied into the ${libdir}/bfd-plugins directory. For GCC based compilations the linker plugin is called liblto_plugin.so.0.0.0, and for Clang based compilations it's called LLVMgold.so πŸ’œ. The GCC plugin is always backwards compatible with earlier versions, so you can just copy the newest one ✨.

  • --target target β€” the optional switch --target bfdname says the archive members are in an object code format that's different from your system's default format 🌍. See
  • --output dirname β€” lets you pick a path to a directory where archive members get extracted πŸ“‚. If you don't specify this, the current directory is used.
Note: even though this option implies an x extraction operation, that option still has to be included on the command line πŸ™ˆ.
  • --record-libdeps libdeps β€” identical to the l modifier, just in long form πŸ’–.
  • --thin β€” makes the specified archive a thin archive πŸ¦‹. If it already exists and is a regular archive, the existing members must be in the same directory as the archive.
  • @file β€” reads command-line options from file 🫧. The options it reads get inserted in place of the original @file option. If the file doesn't exist or can't be read, the option gets treated literally and isn't removed.

Options in the file are separated by whitespace. If you want a whitespace character inside an option, wrap the entire option in single or double quotes. Any character (including a backslash) can be included by putting a backslash in front of it. The file can even contain more @file options of its own, and those get processed recursively πŸŒ€.

✨ SEE ALSO ✨

nm(1), ranlib(1), and the Info entries for binutils πŸ“š.

Copyright (c) 1991-2025 Free Software Foundation, Inc. πŸ’…

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License" πŸ“œ.


That's the whole AR(1) tea, bestie 🫢 binutils 2.45, dated December 3rd, 2025, and this page is officially iconic πŸ‘‘βœ¨ periodt πŸ’œ

πŸ“¦ where this page comes from