pax
can do this all at once. You could do:
cd /backup/path/data && pax -wrs'/-.*$/.etf/' Erp*etf /home/user/data
pax
preserves times by default, but can add -pe
to preserve everything (best done as root) or -pp
to preserve permissions , eg:
cd /backup/path/data && pax -wrs'/-.*$/.etf/' -pe Erp*etf /home/user/data
Otherwise (pax
isn't usually available by default), surely it is better to do a copy then a rename
:
cp -a /backup/path/data/Erp*.etf /home/user/data
rename 's/-.*$/.etf/' /home/user/data/Erp*.etf
This way there is not a different process started for each file.
Most unices don't track a file's creation date¹. “Creation date” is ill-defined anyway (does copying a file create a new file?). You can use the file's modification time, which is by a reasonable interpretation the date at which the latest version of the data was created. If you make copies of the file, make sure to retain the modification time (e.g. cp -p
or cp -a
if you use the cp
command, not bare cp
).
A few file formats have a field inside the file where the creator application fills in a creation date. This is often the case for photos, where the camera will fill in some Exif data in JPEG or TIFF images, including the creation time. Nikon's NEF image format wraps around TIFF and supports Exif as well.
There are ready-made tools to rename image files containing Exif data to include the creation date in the file name. renaming images to include creation date in name shows two solutions, with exiftool and exiv2.
I don't think either tool lets you include a counter in the file name. You can do your renaming in two passes: first include the date (with as high resolution as possible to retain the order) in the file name, then number the files according to that date part (and chuck away the time). Since modern DSLRs can fire bursts of images (Nikon's D4s shoots at 11fps) it is advisable to retain the original filename as well in the first phase, as otherwise it would potentially lead to several files with the same file name.
exiv2 mv -r %Y%m%d-%H%M%S:basename: *.NEF
# exiv2 uses `strftime(3)`, so `%Y%m%d-%H%M%S` returns YYYYMMDD-hhmmss
# :basename: is a naming variable exiv2's `-r`-handle provides. See `exiv2 -h` for more
# Now you have files with names like 20140630-235958_DSCC1234.NEF.
# Note that chronological order and lexicographic order agree with this naming format.
i=10000
for x in *.NEF; do
i=$((i+1))
mv "$x" "${x%-*}_FOO_${i#1}.NEF"
done
${x%-*}
removes the part after the -
character. The counter variable i
counts from 10000 and is used with the leading 1
digit stripped; this is a trick to get the leading zeroes so that all counter values have the same number.
Rename files by incrementing a number within the filename has other solutions for renaming a bunch of files to include a counter.
If you want to use a file's timestamp rather than Exif data, see Renaming a bunch of files with date modified timestamp at the end of the filename?
As a general note, don't generate shell code and then pipe it into a shell. It's needlessly convoluted. For example, instead of
find -name '*.NEF' |
gawk 'BEGIN{ a=1 }{ printf "mv %s %04d.NEF\n", $0, a++ }' |
bash
you can write
find -name '*.NEF' |
gawk 'BEGIN{ a=1 }{ system(sprintf("mv %s %04d.NEF\n", $0, a++)) }'
Note that both versions could lead to catastrophic results if a file name contained shell special characters (such as spaces, '
, $
, `
, etc.) since the file name is interpreted as shell code. There are ways to turn this into robust code, but this isn't the easiest approach, so I won't pursue that approach.
¹ Note that there is something called the “ctime”, but the c
isn't for creation, it's for change. The ctime changes every time anything changes about the file, either in its content or in its metadata (name, permissions, …). The ctime is pretty much the antithesis of a creation time.
Best Answer
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
, useor
(note the line continuations in the above two commands)
If the files are located in a single directory, just run the loop:
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 offind
, 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: