bashmacosterminalgnome-terminal

How to do a loop with variable touch -t command on mac terminal


I'm trying to achieve this:

for i in {01..31}
do
    touch -t 202207$i0000 $i-07-2022.md
done

I have 31 .md files named 01-07-2022.md, 02-07-2022.md ... I basically want to change their creation date respectivelly to the date on their name. Is there someone able to tell me what's wrong with my code?

Thank's.

Solution

for i in {01..31}
do
  SetFile -d "$i/01/2022 00:00:00" $i-07-2022.md
done

Solution

  • The touch command can alter the creation, modification and last access timestamps.

    If you are creating a file with touch, then its creation (birth) timestamp and its last modification timestamp can be set with the -t argument provided. Add the -m option to constrain the change to the modification timestamp.

    With touch, the creation time cannot be set forward of its current value, but can be decremented into the past.

    The ls command is an easy way to see creation (birth) times instead of modification ones. Adding the -U option changes the output from showing the modification data to the creation date.

    On macOS, the XCode Command Line Tools (when installed) provide the SetFile utility to manipulate changes in a file's creation timestamp independently of the modification one. For example:

    SetFile -d "04/01/2011 01:02:03" myfile
    

    changes the creation timestamp of myfile to the value requested. The modification timestamp remains unaltered, but can be changed with the -m option of SetFile.

    SetFile -m "04/01/2022 01:02:03" myfile
    

    Unlike using touch, SetFile can change a file's creation date forward of, or backward from, its current value.

    The following script can be used to alter a file's birthtime while retaining its original modification time.

    cat chtm.sh
    #!/usr/bin/env bash
    # Set a file's birth (creation) timestamp while leaving the modification
    # (mtime) unaltered.
    
    [ $(uname) = "Darwin" ] || { echo "'$0' must be run on macOS"; exit 1; }
    [ $# -ne 2 ] && { printf "Usage: $0 [[CC]YY]MMDDhhmm[.SS] file\n"; exit 1; }
    
    t=$1
    f=$2
    stat -f "BEFORE: btime: %SB, mtime: %Sm" $f || exit 1
    
    m=$(stat -f "%Sm" -t "%Y%m%d%H%M.%S" $f)  # capture the old mtime
    touch  -t $t $f || exit 1                 # update  the btime & mtime
    touch -mt $m $f || exit 1                 # restore the old mtime
    
    stat -f "AFTER : btime: %SB, mtime: %Sm" $f
    exit
    

    A sample run would be:

    touch myfile
    ./chtm.sh 202212311711.00 myfile
    BEFORE: btime: Jan  3 12:19:21 2023, mtime: Jan  3 12:19:21 2023
    AFTER : btime: Dec 31 17:11:00 2022, mtime: Jan  3 12:19:21 2023
    

    As for iterating over your files, changing their timestamps based on the file names, do something like:

    #!/usr/bin/env bash
    for file in *.md
    do
        mm=${file:0:2}
        dd=${file:3:2}
        yy=${file:6:4}
        touch -t ${yy}${mm}${dd}0000 ${file}
    done
    

    This uses shell parameter expansion features to snip the components you need from the file names found.