-
-
Save porg/b6b3160f41c5c6ce7ced5a4982d4aa2e to your computer and use it in GitHub Desktop.
| #!/bin/bash | |
| if [[ -z "$1" || -z "$2" || "$1" == "-h" || "$1" == "--help" ]] ; then | |
| cat <<EOF | |
| USAGE: `basename $0` backupDir targetDir | |
| Loops through all files on root level of backupDir. | |
| For each file in backupDir it tries to find a same named file in targetDir. | |
| - If not found in target (because renamed or removed meanwhile) the file is skipped. | |
| - If found and they have the same modification timestamp nothing is done either. | |
| - If found and the moddates differ the moddate is copied from the backup to the target. | |
| EOF | |
| exit | |
| fi | |
| backupDir=$1 | |
| targetDir=$2 | |
| if [[ ! -d "$backupDir" ]] | |
| then | |
| echo "Error! No directory at path for backupDir:" | |
| echo "$1" | |
| exit | |
| fi | |
| if [[ ! -d "$targetDir" ]] | |
| then | |
| echo "Error! No directory at path for targetDir:" | |
| echo "$2" | |
| exit | |
| fi | |
| backupFiles=$(ls -l1 "$backupDir") | |
| targetFiles=$(ls -l1 "$targetDir") | |
| backupFileCount=$(echo "$backupFiles" | wc -l) | |
| targetFileCount=$(echo "$targetFiles" | wc -l) | |
| echo | |
| echo "Directories to process:" | |
| echo " Backup:$backupFileCount files at: $backupDir" | |
| echo " Target:$targetFileCount files at: $targetDir" | |
| echo | |
| echo "Output format:" | |
| echo | |
| echo " File Name.ext" | |
| echo " Backup's creation date" | |
| echo " Backup's modification date" | |
| echo " Target's modification date" | |
| echo | |
| echo "Symbol at line start of target's moddate:" | |
| echo | |
| echo "√ Backup and target have same moddate. No need to act." | |
| echo "≠ Target's mod-date differs. --> Gets restored from backup." | |
| echo "x No same named file in target directory anymore." | |
| echo | |
| echo | |
| echo "Copying modification timestamps..." | |
| echo | |
| echo "$backupFiles" | while read file | |
| do | |
| echo " $file" | |
| backupFileCreation=$(GetFileInfo -d "$backupDir/$file") | |
| backupFileModification=$(GetFileInfo -m "$backupDir/$file") | |
| echo " $backupFileCreation" | |
| echo " $backupFileModification ───┐" | |
| if [[ -f "$targetDir/$file" ]] ; then | |
| targetFileModification=$(GetFileInfo -m "$targetDir/$file") | |
| if [[ "$backupFileModification" == "$targetFileModification" ]] ; then | |
| echo "√ $targetFileModification √ ─┘" | |
| else | |
| SetFile -m "$backupFileModification" "$targetDir/$file" | |
| echo "≠ $targetFileModification └───> Restored from backup √" | |
| fi | |
| else | |
| echo "x Not in target dir ! ─┘" | |
| fi | |
| echo | |
| done |
Glad that my script could serve as the basis for your need! 👍
Could you outline the main innovations / differences of your script? Am curious… 🧐
- I only scanned its code superficially, e.g. it seems to check for installed tools, and else installs them via brew.
- Also curious whether and how you replaced the deprecated
GetFileInfoandSetFile.
Oh I didn't really make any significant changes. The checking for installed tools, getopt, etc.—those are all part of my usual bash templates—nothing specific to your script, really.
There are no innovations.
I didn't replace the deprecated tools. I'll stick with what works for now :)
Oh actually I did just find a subtle bug in our implementations. My use case is to restore the modification dates of directories, not plain files. But the key here is that the modification dates of deeper subdirectories need to be updated before those of parent subdirectories. That's because any SetFile would not only restore the modification date of a given file or subdirectory but also update the modification date of the parent directory since that's the normal expected behavior of filesystems: if you modify the content of a directory, the directory's modification date is updated. If the restore is done in the wrong order, then any restores would later be overwritten by these automatic updates.
As I said, the solution is to update deep subdirectories before parent directories. Since I'm using the find command, for my script that means I need to use the -depth flag, which means "depth-first traversal". I've just fixed my script. For you it would mean figuring out a way to make ls output in the right order, perhaps by reversing the order by using tac. (Btw, you were asking about "innovations"; I use find instead of ls so that my script can stream an arbitrary number of files and folders. With ls and bash arrays, you may run into hard-coded and/or memory limits).
Of course for many users, they only care about the modification dates of files and not directories, so this subtlety wouldn't matter for them.
@porg Actually, by demand, I did just port to using gdate, gstat, and gtouch so that there's no reliance on the deprecated GetFileInfo and SetFile tools (and now works for Linux or wherever the GNU coreutils tools are supported)
Thanks for your script. I customized it to fit my style: https://github.com/huyz/trustytools/blob/master/contrib/restore-modified-date.sh