Skip to content

The ar Command in Linux: Create and Extract Archives

8 min read

Applies to: GNU ar from binutils 2.44 (Debian 13), 2.46 (Ubuntu 26.04) and 2.41 (AlmaLinux 10), all tested

To extract an ar archive, run ar x archive.a: every member is written to the current directory. ar t archive.a lists the members first, and ar rcs archive.a file1 file2 creates an archive. The same commands open a Debian or Ubuntu .deb package, because a .deb file is an ar archive: ar x package.deb gives you debian-binary, control.tar.* and data.tar.*, and you then unpack the tar files with tar.

What ar is and where it comes from

ar is the archiver from GNU binutils. It joins files into one archive without compressing them and without folder paths. Today you meet it in two places: static libraries (.a files that the compiler links into programs) and .deb packages. For backups or for sending a folder to someone, use tar instead (see how to create and extract a tar file).

If the command is missing, install binutils: sudo apt install binutils on Debian and Ubuntu, sudo dnf install binutils on AlmaLinux and Rocky Linux. The AlmaLinux 10 container image in our lab already had it.

The syntax is ar OPERATION[MODIFIERS] ARCHIVE [MEMBERS]. The first argument is always a group of letters: one operation (such as x, t or r) plus optional modifiers. A leading dash is optional, so ar x and ar -x are the same.

Quick reference

  • ar t file.a: list the members.
  • ar tv file.a: list with permissions, owner, size and date.
  • ar x file.a: extract all members into the current directory.
  • ar xv file.a: extract and print each name.
  • ar x file.a member.o: extract one member.
  • ar xo file.a: extract and keep the dates stored in the archive.
  • ar p file.a member: write one member to standard output.
  • ar rcs file.a a.o b.o: create the archive or replace members, without a warning, and write a symbol index.
  • ar q file.a c.o: append without checking for an existing member of that name.
  • ar d file.a b.o: delete a member.
  • ar s file.a: rebuild the symbol index (the same as ranlib file.a).

Create an archive (a static library)

  1. Compile the source files into object files:
    gcc -c hello.c bye.c
  2. Put the object files into an archive. r inserts or replaces members, c creates the archive without the warning ar: creating libgreet.a, and s writes the symbol index that the linker uses:
    ar rcs libgreet.a hello.o bye.o
  3. Check the result (lab output, Debian 13):
    $ ar t libgreet.a
    hello.o
    bye.o
    $ nm -s libgreet.a
    
    Archive index:
    hello in hello.o
    bye in bye.o
    ...
  4. Link a program against it: gcc main.c -L. -lgreet -o app. In our test, ./app printed the lines from both functions.

In our tests, GNU ar also wrote the index when s was left out. Keep s anyway: it is the documented way to ask for the index. The S modifier turns the index off.

List the contents and read the dates

ar tv shows the details of each member. Lab output from Debian 13:

$ ar tv libgreet.a
rw-r--r-- 0/0   1376 Jan  1 00:00 1970 hello.o
rw-r--r-- 0/0   1360 Jan  1 00:00 1970 bye.o

The zeros and the 1970 date are not an error. On Debian 13 and Ubuntu 26.04, ar works in "deterministic mode" (D) by default: it stores zero for owner, group and timestamp, so the same input always gives an identical archive. ar rcsU stores the real dates instead. On AlmaLinux 10, ar --help marks U as the default, and our archive there kept the real time. Add O (ar tvO) to also show each member's offset in the file.

Extract files from an ar archive

  1. Make a working folder, because ar x writes into the current directory and overwrites files with the same names:
    mkdir extracted && cd extracted
  2. Extract everything, with v to see each file:
    $ ar xv ../libgreet.a
    x - hello.o
    x - bye.o
  3. To extract a single member, name it after the archive: ar x ../libgreet.a bye.o.
  4. To extract into another folder without changing directory, use --output. The folder must already exist; with a missing folder our test printed out2/hello.o: No such file or directory.
    mkdir out
    ar x --output out libgreet.a

Extracted files get the current time. ar xo sets the dates stored in the archive instead, which gave 1970-01-01 for our deterministic archive.

Extract a .deb package with ar

This is useful when you want to look inside a package without installing it, or need its files on a system without dpkg. Lab run on Debian 13 with the hello package:

  1. Download the package (or use a .deb you already have):
    apt-get download hello
  2. List the members:
    $ ar t hello_2.10-5_amd64.deb
    debian-binary
    control.tar.xz
    data.tar.xz
  3. Extract them and check the format version:
    $ mkdir hello-deb && cd hello-deb
    $ ar x ../hello_2.10-5_amd64.deb
    $ cat debian-binary
    2.0
  4. Read the package information: control.tar.xz holds the control file (name, version, dependencies), md5sums and any install scripts.
    $ tar -tf control.tar.xz
    ./
    ./control
    ./md5sums
  5. Unpack the program files from data.tar.xz into a folder:
    $ mkdir pkg && tar -xf data.tar.xz -C pkg
    $ pkg/usr/bin/hello
    Hello, world!

Ubuntu packages are compressed with zstd. On Ubuntu 26.04 the same package contained control.tar.zst and data.tar.zst. If the zstd program is missing, tar stops with:

tar (child): zstd: Cannot exec: No such file or directory

Install it with sudo apt install zstd and run tar -xf data.tar.zst again. You can also skip the temporary files and send one member straight into tar: ar p hello_2.10-5_amd64.deb data.tar.xz | tar -xJ (use tar --zstd -x for .zst).

The same steps work on AlmaLinux 10, which has no dpkg: ar x and tar -xf data.tar.xz unpacked a Debian package there in our test. Unpacking only gives you the files. It does not run the package scripts or install dependencies, so use it to inspect packages, not to install software. To install a .deb, see how to install a .deb file on Debian and Ubuntu.

On Debian and Ubuntu, dpkg-deb does the same job in one step and handles every compression format itself (it worked on Ubuntu 26.04 before zstd was installed):

dpkg-deb -x hello_2.10-5_amd64.deb pkg      # program files
dpkg-deb -e hello_2.10-5_amd64.deb control  # control files and scripts
dpkg-deb -c hello_2.10-5_amd64.deb          # list the files

If you repack a package by hand, the member order matters: according to the Debian deb(5) manual, debian-binary must be first. An archive we built as ar rc new.deb debian-binary control.tar.xz data.tar.xz passed dpkg-deb -I; with control.tar.xz first, dpkg-deb refused it with file 'wrong.deb' is not a Debian binary archive (try dpkg-split?). For real packages, build with dpkg-deb --build.

Add, replace and delete members

  • ar r libgreet.a bye.o replaces the existing bye.o. Add u (ar ru) to replace only when your file is newer.
  • ar q libgreet.a bye.o appends without checking names. Running it twice left two bye.o members in our test, so prefer r unless you need the speed.
  • ar d libgreet.a bye.o removes a member. With duplicate names it removed one of them.
  • After changing a library, run ar s libgreet.a or ranlib libgreet.a if you built it with S.

Common errors

  • ar: nosuch.a: No such file or directory: wrong archive name or path.
  • ar: notes.txt: file format not recognized: the file is not an ar archive. Every ar archive starts with the 8 bytes !<arch> followed by a newline; check with head -c 8 file or file file (it printed current ar archive for our library).
  • no entry nope.o in archive: the member name does not exist. Check the spelling with ar t. In our test ar still returned exit code 0, so scripts should not rely on the exit code here.
  • ar: invalid option -- 'g' after ar libgreet.a: the operation letters are missing, so ar read the archive name as options. Write ar t libgreet.a.

Related articles: create and extract a tar file, install a .deb file, zstd compression on Linux and what GCC is. All Ucartz KVM VPS plans include full root access, so you can install binutils and build your own libraries.

Official documentation: GNU binutils: ar and deb(5) package format.

Was this answer helpful?

Still stuck? Open a ticket