Pro Backup
Pro Backup

Reputation: 761

How to create directory structure with identical metadata/timestamps on consecutive runs using bash?

$ install -m755 -d "/tmp/usr/lib/modules/4.14.4-1-ARCH/kernel"

creates multiple new directory entries inside a bash script that creates a Linux initramfs file. For the file/folder metadata to be consistent between runs, the idea is to reference the folder timestamps to the kernel itself, with touch --reference=<source_file> <new_created_directory>.

The individually to be touched folders can be retrieved via install --verbose command, like:

$ install -v -m755 -d "/tmp/usr/lib/modules/4.14.4-1-ARCH/kernel"
install: creating directory '/tmp/usr'
install: creating directory '/tmp/usr/lib'
install: creating directory '/tmp/usr/lib/modules'
install: creating directory '/tmp/usr/lib/modules/4.14.4-1-ARCH'
install: creating directory '/tmp/usr/lib/modules/4.14.4-1-ARCH/kernel'

Directions

  1. redirect output of file descriptor #1 to an array, and loop through the array. Maybe the array is not even nessary and the install -v -d output can be immediately piped into a readline type of code block.
  2. directory traversal from the created directory up till root of temporary initramfs, /tmp in the example above.

How to create a directory structure with identical metadata on consecutive runs? For example the necessary touch command loop and parameter expansions (PE) to match the newly created directories by install?


The parent bash script is writing a skeleton minimal Linux file and folder structure to a temporary location, that will finally be compressed into an initramfs structure. The goal is to be able to recreate binary identical initramfs files on consecutive script runs. By default the files are identical, but the metadata is not due to different creation/access timestamps.

Upvotes: 1

Views: 181

Answers (1)

janos
janos

Reputation: 124704

After the directory structure is ready to create the initramfs based on it, set the timestamp of all files and directories to a reference point. You can use the find command for this:

find path/to/basedir -exec touch -r "$reference_file" {} +

If you want to touch only files that were created by install commands, than you can create a marker file that you can use with the -newer predicate of find, for example:

marker=/tmp/marker
touch "$marker"
install ...

find path/to/basedir -newer "$marker" -exec touch -r "$reference_file" {} +

If you want touch specifically the files printed by install -v -d ..., where all the output lines are expected to have this format:

install: creating directory '...'

Then you could pipe the output of install to a loop that reads line by line, and extracts the paths by chopping the prefix of the line until the first ', and chopping off everything from the last ':

... | while read -r line; do
    [[ $line = *'install: creating directory '* ]] || continue
    line=${line#*\'}
    line=${line%\'*}
    touch -r "$reference_file" "$line"
done

Upvotes: 2

Related Questions