TIL about the install command on *nix systems. A quick GitHub search for the term brought up a ton of matches1. I’m surprised I just found out about it now.

Often, in shell scripts I need to:

  • Create a directory hierarchy
  • Copy a config or binary file to the new directory
  • Set permissions on the file

It usually looks like this:

# Create the directory hierarchy. The -p flag creates the parent directories
# if they don't exist
mkdir -p ~/.config/app

# Copy the current config to the newly created directory. Here, conf already
# exists in the current folder
cp conf ~/.config/app/conf

# Set the file permission
chmod 755 ~/.config/app/conf

Turns out, the install command in GNU coreutils2 can do all that in one line:

install -D -m 755 conf ~/.config/app/conf

You can check the file status with:

stat ~/.config/app/conf

On my machine, this prints:

 File: /Users/rednafi/.config/app
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: 1,16    Inode: 16439606    Links: 1
Access: (0755/-rwxr-xr-x)  Uid: (  501/ rednafi)   Gid: (   20/   staff)
Access: 2024-07-28 20:51:42.793765043 +0200
Modify: 2024-07-28 20:51:42.793765043 +0200
Change: 2024-07-28 20:51:42.793907876 +0200
Birth: 2024-07-28 20:51:42.793765043 +0200

The -D flag directs install to create the destination directories if they don’t exist, and the -m flag sets file permissions. The result is the same as the three lines of commands before.

It’s common for Makefiles in C/C++ projects to install binaries like this:

install -D -m 744 app_bin /usr/local/bin/app_bin

It copies app_bin to /usr/local/bin, creates the parent directory hierarchy if necessary, and sets permissions on the binary so only the current user has read, write, and execute permissions, while others have read-only access.

You can also set directory permissions:

install -d -m 600 foo/bar/bazz

This creates the directory hierarchy first and then sets the permission. Here’s how they look:

tree foo

Output:

foo
└── bar
    └── bazz

3 directories, 0 files

Then you can copy a file to the destination and set file permissions with another install command if needed.

You can also set user or group ownership while copying a file:

install -D -m 644 -o root -g root seed.db /var/lib/app/seed.db

This command copies seed.db to the destination, creates the directory if needed, and gives access to the root user and group with the -o and -g flags, respectively.

There are a few other options you can read about in the man pages, but I haven’t needed anything beyond the above.

Recent posts