Rename multiple files, add date in the middle

find . -type f -name '*.txt' -exec sh -c '
    now=$( date +%Y%m%d%H%M )
    for pathname do
        mv "$pathname" "${pathname%.txt}.$now.txt"
    done' sh {} +

This would find all pathnames of regular files in or below the current directory, whose names end in .txt. For batches of these, a short shell script is called. This script will first get the timestamp (this is had only once for each batch, for efficiency) and then loop over the given pathnames.

For each pathname, it will rename it by removing the final .txt (using ${pathname%.txt}), and adding a dot, the timestamp and .txt.

This has not been tested on Solaris, but uses only standard components and options etc.

To compute the timestamp only once, before calling find, use

now=$( date +%Y%m%d%H%M ) \
find before (but without assigning to now)...


env now="$( date +%Y%m%d%H%M )" \
find before (but without assigning to now)...

(note the line continuations in the above two commands)

If the files are located in a single directory, just run the loop:

now=$( date +%Y%m%d%H%M )
for pathname in ./*.txt; do
    mv "$pathname" "${pathname%.txt}.$now.txt"

This assumes that the pattern ./*.txt matches all names that you'd like to rename.


  • Understanding the -exec option of `find`

Your {}.$(date +'%Y%m%d%H%M').txt does not work portably. It may work with some implementations of find, but an implementation is not required to expand {} to the current pathname if the {} occurs together with another string.

The relevant text from the POSIX standard is:

A utility_name or argument containing only the two characters {} shall be replaced by the current pathname. If a utility_name or argument string contains the two characters {}, but not just the two characters {}, it is implementation-defined whether find replaces those two characters or uses the string without change.

An alternative, though am not sure how solaris compatible it is....

to=$(date +%Y%m%d%H%M).txt
find * -prune -type f -name "*.$from" -exec sh -c 'mv "$3" "${3%.$1}.$2"' sh "$from" "$to" {} ';'

Stolen shamelessly from the unix.stackexhange link given by @Kulasananda but I like the way that the call from sh composes the variables for sh -c mv.