5

I want to rename all files in a folder, including a current time stamp in the name, retaining the original extension, in Solaris, like this:

test1.txt > test1.date.txt

I tried this, but I lose the first part of the name:

find * -prune -type f -name '*.txt' -exec mv {} {}.$(date +'%Y%m%d%H%M').txt \;

What am I missing ?

8
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 ...as before (but without assigning to now)...

or

env now="$( date +%Y%m%d%H%M )" \
find ...as 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"
done

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

Related:


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.

  • You might want mv -- fname ... in case the names start with hyphens – D. Ben Knoble Jan 25 at 22:49
  • 2
    @D.BenKnoble They won't start with dashes. find will add the search path (at least ./) to each pathname, and the loop alternative will also always have ./ before any filename due to the way I wrote the pattern. – Kusalananda Jan 25 at 22:56
3

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

from=txt
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.

Sweet.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.