Working on recordsdata in a listing tree
To function on all of the recordsdata within the present listing, when you’re operating a command that accepts a number of file names, you need to use the sample *
. To run extra advanced code, use a for loop.
mycommand *
for x in *; do …; executed
To function on recordsdata in subdirectories as properly, in zsh or fashionable bash (from Brew/MacPorts/Fink/…) however not in /bin/bash
, use the **/*
sample:
mycommand **/*
for x in **/*; do …; executed
You’ll be able to limit the file names by altering the final *
to a sample, e.g. *.jpeg
to solely act on recordsdata with the .jpeg
extension.
(There are a variety of issues however they do not matter right here so I will not go into them. All instructions on this reply deal with areas in file names accurately.)
As a further security, I am going to present methods to solely function on recordsdata which might be older than a sure threshold. This manner, when you run the command twice, it will not over-shift the second time. In zsh, that is straightforward with the glob qualifier my+4
to solely match recordsdata modified a minimum of 4 years in the past. In bash, you need to use the -nt
conditional expression to check the file with a reference file, nevertheless it’s much less handy.
Alternatively, to function on recordsdata in subdirectories, you need to use discover
.
discover . -name '*.jpeg' -newermt 202001010000 -exec sh -c '…' {} ';'
Observe that the date filtering assumes that the file’s modification occasions are the dates when the images have been taken, not the dates once you copied them lately. Should you solely need to change the picture metadata, skip the date filtering.
Picture metadata
Since these are photos, you may most likely need to modify their Exif metadata. There are a number of instruments that may do that, I am going to present methods to use exiftool (open-source, accessible from Homebrew and different bundle sources).
Exiftool has a handy command to shift occasions by a specific amount. (You are not the primary to run into this drawback.) You do should be just a little cautious as a result of the unique date vary features a leap day, so you may’t simply add years/months/days independently. All dates must shift by 179 days (to June 28, 2013) plus 9×365+2 (from 2013 to 2022, together with two leap days), i.e. 3466 days whole. You may also inform exiftool to reset the file’s modification time to the Exif metadata (by default, the file’s modification time can be the present time, since you have simply modified the file).
exiftool -if '$CreateDate lt "2020:01:01"' -AllDates+='3466 12:42' -'FileModifyDate
File modification occasions
You should use the date
command to print both a specific time or the modification time of a file in numerous codecs. (Each the built-in /bin/date
and the GNU model have these capabilities, however with barely totally different syntax; right here I am going to use the choices for /bin/date
.) So the plan is, for every file:
- Use
date -r FILENAME +%s
to get the file’s modification time as various seconds since a set origin. - Use shell arithmetic so as to add the specified variety of seconds to the time from step 1.
- Use
date
to print the time calculated at step 2 in a format thatcontact
understands. - Use
contact
to set the file’s modification time.
We are able to additionally use date
and arithmetic to calculate the variety of seconds so as to add to the time.
echo $(($(date -j -f %YpercentmpercentdTpercentHpercentM 20220628T1142 +%s) - $(date -j -f %YpercentmpercentdTpercentHpercentM 20121231T2300 +%s)))
Let’s put this all collectively utilizing discover
:
delta=$(($(date -j -f %YpercentmpercentdTpercentHpercentM 20220628T1142 +%s) - $(date -j -f %YpercentmpercentdTpercentHpercentM 20121231T2300 +%s)))
discover . -type f ! -newermt 202001010000 -exec sh -c 't=$(date -r "$1" +%s); contact -t $(date -r $((t + $0)) +%YpercentmpercentdpercentHpercentM.%S) "$1"' $delta {} ';'
And this is a zsh resolution:
delta=$(($(date -j -f %YpercentmpercentdTpercentHpercentM 20220628T1142 +%s) - $(date -j -f %YpercentmpercentdTpercentHpercentM 20121231T2300 +%s)))
for x in **/*.jpeg(.my+4); do
t=$(date -r "$x" +%s)
contact -t $(date -r $((t + delta)) +%YpercentmpercentdpercentHpercentM.%S) $x
executed