Files and directories
install
Copy files into place and set their mode, owner and group in one step; can also create directories.
install [OPTION...] SOURCE... DEST | install -d [OPTION...] DIRECTORY...
Despite the name, install has nothing to do with package managers. It is cp plus
chown plus a permission change, done in one command: copy this file there, with this mode,
owned by this user. Makefiles use it in their install targets, and deployment scripts use it
to put configuration files and binaries in place with exactly the permissions they need.
Two details make it different from cp. The default mode is 755 (rwxr-xr-x), not the
source's mode, so pass -m 644 for non-executable files. And it replaces the destination by
removing it first instead of writing into it, so a program that is running from the old file
keeps working.
install -d creates directories (with parents) and sets their mode and owner, like mkdir -p
with extra options. -D creates the destination's missing parent directories before copying.
Examples
Install a script as an executable
mkdir -p bin
install scripts/greet.sh bin/greet
ls -l bin/greet
bin/greet installer
-rwxr-xr-x 1 dev dev 37 Oct 31 20:19 bin/greet Hello, installer!
The file is copied and given mode 755 (-rwxr-xr-x), regardless of the source's mode, so
it runs straight away.
Install a config file with a specific mode
mkdir conf
install -m 644 data/settings.conf conf/
install -m 600 .env conf/
ls -lA conf
total 1 -rw------- 1 dev dev 42 Oct 31 20:19 .env -rw-r--r-- 1 dev dev 149 Oct 31 20:19 settings.conf
-m sets the mode. Plain data gets 644, and a file holding secrets gets 600, readable
only by the owner.
Create directories with a given mode
install -d -m 750 deploy/releases deploy/shared/logs
ls -ld deploy/releases deploy/shared deploy/shared/logs
drwxr-x--- 2 dev dev 2 Oct 31 20:19 deploy/releases drwxr-xr-x 3 dev dev 3 Oct 31 20:19 deploy/shared drwxr-x--- 2 dev dev 2 Oct 31 20:19 deploy/shared/logs
-d treats the arguments as directories and creates missing parents. The mode applies to
the named directories; parents created on the way (deploy/shared) get the default mode.
Copy into a path that does not exist yet
install -D -m 644 src/lib/helpers.py dist/lib/python/helpers.py
find dist
dist dist/lib dist/lib/python dist/lib/python/helpers.py
-D creates every missing directory leading up to the destination, then copies the file.
Set owner and group while copying
Setup run before this example
useradd -M -U -r appinstall -o app -g app -m 640 data/config.json /etc/demo-config.json
ls -l /etc/demo-config.json
-rw-r----- 1 app app 244 Oct 31 20:19 /etc/demo-config.json
-o and -g set the owner and group (this needs root). One command replaces the usual
cp, chown and chmod sequence, with no moment where the file has the wrong owner.
Show what is installed where
mkdir -p out
install -v -m 644 data/*.csv out/
'data/sales.csv' -> 'out/sales.csv' 'data/users.csv' -> 'out/users.csv'
-v prints each copy. With several sources, the destination must be a directory.
Keep the previous version
Setup run before this example
mkdir -p bin
install scripts/greet.sh bin/greetinstall -b -S .old scripts/backup.sh bin/greet
ls bin
greet greet.old
-b renames the file being replaced, and -S .old sets the suffix (the default is ~).
Skip the copy when nothing changed
Setup run before this example
mkdir -p bin
install -m 755 scripts/greet.sh bin/greet
touch -d "2026-01-01" bin/greetinstall -C -m 755 scripts/greet.sh bin/greet
ls -l --time-style=+%F bin/greet
-rwxr-xr-x 1 dev dev 37 2026-01-01 bin/greet
-C compares content, owner and mode first and leaves an identical destination alone, so
its old timestamp survives and tools that watch modification times see no change.
install replaces the file, cp overwrites it in place
Setup run before this example
mkdir -p bin
install scripts/greet.sh bin/greetls -i bin/greet
install scripts/greet.sh bin/greet && ls -i bin/greet
cp scripts/greet.sh bin/greet && ls -i bin/greet
9811877 bin/greet 9466071 bin/greet 9466071 bin/greet
Each install produces a new file with a new inode number; cp wrote into the existing
one, so the number stayed. A program running from the old file keeps its own copy with
install, while overwriting a running binary in place with cp can fail with "Text file
busy" or crash it. In Makefiles, install -m 755 prog $(DESTDIR)$(PREFIX)/bin/ is the
standard install step for this reason.
Common pitfalls
install file destmakesdestexecutable (mode 755) even for a text file. Always pass-m 644for data and config files.installfollows symlinks in the source and copies the target file; it cannot install a symlink.With one source and a destination that is an existing directory, the file goes inside it. Use
-Tto treat the destination as a file name and fail otherwise.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
-D,-t,-Tand-vare GNU options. BSD/macOSinstallshares-d,-m,-o,-g,-b,-Cand-c(which is a no-op on GNU, kept for compatibility).
Options worth knowing
A selection, described in our own words. For the full list, see install(1) or install --help.
| Option | What it does |
|---|---|
-m, --mode MODE | Set the permission mode (default 755). |
-o, --owner OWNER | Set the owner (root only). |
-g, --group GROUP | Set the group. |
-d, --directory | Treat all arguments as directories to create. |
-D | Create missing parent directories of the destination. |
-C, --compare | Do not replace a destination that is already identical. |
-b | Back up each existing destination file. |
-S, --suffix SUFFIX | Use SUFFIX for backups instead of ~. |
-p, --preserve-timestamps | Keep the source's access and modification times. |
-s, --strip | Strip symbol tables from installed binaries. |
-t, --target-directory DIR | Copy all sources into DIR. |
-T, --no-target-directory | Treat DEST as a file name, never a directory. |
-v, --verbose | Print each file or directory created. |
-c | Ignored; accepted for compatibility with old BSD install. |
Related
cpCopy files and directories, optionally keeping their timestamps, permissions and links.chownChange the owner and/or group of files and directories.mkdirCreate directories, optionally with all missing parents.mktempCreate a temporary file or directory with a unique, unpredictable name and print that name.lnMake links between files, symbolic (-s) or hard.