Skip to content
Linux Basics: Copy Files with Explicit Modes Using GNU install

Linux Basics: Copy Files with Explicit Modes Using GNU install

October 27, 2026

A local staging directory often needs predictable permission bits. GNU install can create parent directories and copy a file with an explicit mode. Practice only inside a fresh temporary directory, without root or system paths.

Prepare a scratch directory

Tested on Linux with GNU coreutils 9.7 and GNU Bash 5.2.37. You need the named runtime, Bash, a text editor, and the standard mktemp, rm, and rmdir utilities. The script creates a separate temporary fixture directory and removes only that directory on exit. It does not operate on your existing files.

Keep using the same terminal. Stop if setup fails, before saving the source:

start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1

Run the example

Save this as demonstrate-gnu-install.sh:

#!/usr/bin/env bash
set -euo pipefail
export LC_ALL=C
fixture_dir="$(mktemp -d)"
trap 'rm -rf -- "$fixture_dir"' EXIT
cd -- "$fixture_dir"
printf 'mode=preview\n' > source.conf
install -D -m 0640 source.conf stage/etc/demo.conf
cmp source.conf stage/etc/demo.conf
printf 'Installed mode: %s\n' "$(stat -c %a stage/etc/demo.conf)"
test "$(stat -c %a stage/etc/demo.conf)" = 640
printf 'mode=ready\n' > source.conf
install --backup=numbered -m 0600 source.conf stage/etc/demo.conf
printf 'Current contents:\n'
cat stage/etc/demo.conf
printf 'Previous contents:\n'
cat stage/etc/demo.conf.~1~
test "$(stat -c %a stage/etc/demo.conf)" = 600
test "$(cat stage/etc/demo.conf.~1~)" = mode=preview
printf 'Updated mode: %s\n' "$(stat -c %a stage/etc/demo.conf)"

Run it:

bash demonstrate-gnu-install.sh

Observed output:

Installed mode: 640
Current contents:
mode=ready
Previous contents:
mode=preview
Updated mode: 600

Read the result

-D creates missing parent directories before copying. -m sets the destination file mode rather than inheriting whatever mode the source happens to have. The second copy asks for a numbered backup, preserving the old destination under a suffix. The checks compare contents and exact mode bits after both operations.

Apply it carefully

The mode here applies to the copied file, not a blanket policy for every created parent. GNU install defaults are not the same as ordinary cp; always choose the mode appropriate to your destination. Backups may contain sensitive old contents and need their own retention policy. This is a local copy demonstration, not an atomic application deployment or a package-manager replacement. No ownership changes or privileged writes are needed.

The official reference describes the API and its options. The checks above cover the specific fixture, not every possible input or environment.

Clean up

Remove the source and then the empty practice directory:

rm -- demonstrate-gnu-install.sh
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dir

If the directory is not empty, inspect the remaining files rather than deleting unknown contents.

Acknowledgements

This post was created with assistance from AI.

Last updated on