#!/usr/bin/env sh # compat: +ash +bash +dash +hush -ksh +mksh +oksh +osh +posh +yash +zsh decently() ( ### @- ### given a list of directories, update the last-modified timestamp ### of each argument to that of the most recent file that it contains. ### ### note that *files* are found recursively, but only the ### *outermost directory* (the one specified by argument) ### has its timestamp updated. symlinks are followed. ### `.git` subdirectories are skipped over. ### the timestamps of subdirectories are ignored. [ -n "$1" ] || { printf '%s: missing directory argument\n' decently >&2; return 1; } local arg= dir= latest= prev= ts= fails= succs=0 finder() { find "$dir" -type f "$@" \ '!' \ '(' -path '*/.git/*' \ -or -path '*/CVS/*' \ -or -path '*/CVSROOT/*' \ -or -path '*/__pycache__/*' \ -or -path '*/[Dd]esktop.ini' \ -or -path '*/Thumbs.db' \ -or -path '*/.DS_Store' \ ')' \ -exec ls -t1 '{}' + \ 2>/dev/null \ | while read -r f; do printf '%s\n' "$f" break done } for arg; do dir="$(readlink -f -- "$arg")" || continue [ -d "$dir" ] || { printf '%s: not a directory: %s\n' decently "$dir" >&2; continue; } prev= latest="$(finder)" || continue while [ -n "$latest" ]; do prev="$latest" latest="$(finder -newer "$latest")" || break done [ -e "$prev" ] || { printf '%s: no valid files found: %s\n' decently "$dir" >&2; continue; } ts="$(date -u '+%s' -r "$prev")" dir="${dir%/}/" # ensure dir has a trailing slash printf '%s\t%s\n' "$ts" "${arg%/}/${prev#$dir}" touch -c -r "$prev" "$dir" || continue : $(( succs+=1 )) done fails=$(( $# - succs )) [ $fails -le 255 ] || fails=255 return $fails ) [ -n "${preload+-}" ] || decently "$@"