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 asranlib file.a).
Create an archive (a static library)
- Compile the source files into object files:
gcc -c hello.c bye.c
- Put the object files into an archive.
rinserts or replaces members,ccreates the archive without the warningar: creating libgreet.a, andswrites the symbol index that the linker uses:ar rcs libgreet.a hello.o bye.o
- 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 ...
- Link a program against it:
gcc main.c -L. -lgreet -o app. In our test,./appprinted 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
- Make a working folder, because
ar xwrites into the current directory and overwrites files with the same names:mkdir extracted && cd extracted
- Extract everything, with
vto see each file:$ ar xv ../libgreet.a x - hello.o x - bye.o
- To extract a single member, name it after the archive:
ar x ../libgreet.a bye.o. - To extract into another folder without changing directory, use
--output. The folder must already exist; with a missing folder our test printedout2/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:
- Download the package (or use a
.debyou already have):apt-get download hello
- List the members:
$ ar t hello_2.10-5_amd64.deb debian-binary control.tar.xz data.tar.xz
- 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
- Read the package information:
control.tar.xzholds thecontrolfile (name, version, dependencies),md5sumsand any install scripts.$ tar -tf control.tar.xz ./ ./control ./md5sums
- Unpack the program files from
data.tar.xzinto 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.oreplaces the existingbye.o. Addu(ar ru) to replace only when your file is newer.ar q libgreet.a bye.oappends without checking names. Running it twice left twobye.omembers in our test, so preferrunless you need the speed.ar d libgreet.a bye.oremoves a member. With duplicate names it removed one of them.- After changing a library, run
ar s libgreet.aorranlib libgreet.aif you built it withS.
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 withhead -c 8 fileorfile file(it printedcurrent ar archivefor our library).no entry nope.o in archive: the member name does not exist. Check the spelling withar t. In our test ar still returned exit code 0, so scripts should not rely on the exit code here.ar: invalid option -- 'g'afterar libgreet.a: the operation letters are missing, so ar read the archive name as options. Writear 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.