Script to re-write dates in file names

Annnnnd I’m done.

Did I say “done?” Now using a regex that will (should) only pick viable dates, although other strings can match. Notably a time string that meets the [01-12].[01-31].[00-99] format. Also added some error checking… or at least that’s the idea. Unsure if working at this time. I don’t believe it do. Only if `date` can’t reformat the string it’s fed will it be able to notice, but that is printed to stdout already. It’s the “Warning:” lines that are ambiguous.

Removed the “error checking” which didn’t work. I suggest making note of any errors reported to stdout while the script runs.

The main extended regex that matches the mm.dd.(yy)yy pattern is now a variable.

#!/bin/sh
# http://strawhousepig.net/

# The following `egrep` (or `grep -E`) should prove useful when checking the
# storage file. If your text editor supports grep based 'find all' you
# may be able to highlight the original text that is to be changed.
# egrep -nv '(1[0-2]|0?[1-9])[.-/,]([0-2]?[1-9]|[1-3][0-1])[.-/,](20)?[0-9]{2}(\.[[:alnum:]]+)?[[:space:]]/'

# Name of file in which to store 'mv' statements.
mvstore="mvstore.sh"

# The number of parentheses here affects the `sed` for $e. Currently "\4".
dateregex="(1[0-2]|0?[1-9])[.-/,]([0-2]?[1-9]|[1-3][0-1])[.-/,](20)?[0-9]{2}"

usage="
This script looks recursively for the date pattern mm.dd.yy and similar
in file and directory names beginning at 'pwd'. It then generates an 'mv'
statement for each item with the pattern re-written by 'sed' & 'date'
to yyyy-mm-dd.

Running the '-e' option without first creating and checking the storage
file is not recommended.

-w Write the 'mv' statements to the file '$mvstore'
in the present working directory.
-e Evaluate the 'mv' statements as they are generated.
-h Displays this helpful text.
\n"

function mvdatef() {
# Here, 'tail' reverses the order of 'find' after 'egrep' filters the result.
# That way files in a directory are renamed before the directory is.
# 'find' might be able to use the regex, but I couldn't work it out. YMMV.
# This only looks for the pattern at the end of the line or just before an extension.
# If something isn't working, the regex here is probably where it started.
find "`pwd`" | egrep '[/[:space:]]'"$dateregex"'(\.[[:alnum:]]+)?$' | tail -r | while read a
do

# Escape certain characters so they don't wreck the 'mv' statement later.
# double quote, single quote, parens, ampersand, dollar sign, and space.
# Single quote, parens, and ampersand are escaped for the shell after breaking out of the 'sed' statement.
b=$(echo "$a" | sed -E 's/(["'\'\(\)\&'[:space:]$])/\\\1/g')
if [ "$b" == "" ]; then
echo "Error: Could not escape $a" >> $mvstore
fi
# Suck out the last instance of our hated date pattern (00.00.00 or 00.00.0000).
# Also replace dashes, slashes (not working :| ), and errant commas for dots
# because we've come too far not to.
c=$(echo "$a" | egrep -o "$dateregex" | tail -1 | sed -E 's/[-/,]/\./g')
if [ "$c" != "" ]; then
# 'date' will not accept a 2 OR 4 digit year.
if [ $(echo $c | egrep -o "[0-9]{4}$") ]; then
dform="%m.%d.%Y"; else
dform="%m.%d.%y"
fi
d="$(date -j -f "$dform" "$c" "+%Y-%m-%d")"
if [ "$d" == "" ]; then
echo "Error: Could not format date from $c" >> $mvstore
fi
# This is the 'sed' that finds the date and replaces it with what we made just above.
# It looks for the pattern at the end of the line (path) but includes the extension if there.
# It is possible that a version number of some sort will also match.
# Also possible to do away with the EOL in the regex and just go for the pattern.
e="$(echo "$b" | sed -E 's/'"$dateregex"'(\.[[:alnum:]]+)?$/'$d'\4/')"
if [ "$e" == "" ]; then
echo "Error: Could not replace $c in $a" >> $mvstore
fi
# After all that dicking around, this is the mv statement.
f="mv -- $b $e"

if [ $1 ]; then
eval $f
else
echo "$f" >> "$mvstore"
fi
else
echo "Error: $c - Could not pull viable date from $b" >> $mvstore
fi
done
}

if [[ $1 = "-h" ]] ; then
printf "$usage"
exit
elif [[ $1 = "-e" ]]; then
echo "Evaluating 'mv' statements as they are generated..."
mvdatef -e
elif [[ $1 = "-w" ]]; then
echo "Generating file `pwd`/$mvstore and writing 'mv' statements to it..."
printf "#/bin/sh\n# `date`\n" > "$mvstore"
mvdatef
else
printf "$usage"
exit
fi

Original, less-good version: http://strawhousepig.net/shell-script-to-re-format-poor-date-format-in-filenames/

Shell script to re-format poor date format in filenames

New, more-good version here: New script to re-write dates in file names

After testing and some using, this is going to change to just write the mv statements to a file and to accept an argument to run them instead. No logging since that will serve the same purpose. This post does not contain the final version. It’s here for the sake of history.

And boom. Or so I hope. This *should* handle dates as “01.02.03” and the equivalent “01.02.2003”.
To-do: Check for administrator privileges or just write the log to ~/. MacOS (nee OS X (nee Mac OS)) has a default user log directory, but GNU does not. I suppose we could check for “~/.log/” and mkdir if false…

Title explains it pretty well. Uses egrep to find date, sed to edit it, mv to rename, and read for user confirmation prompt. Which, btw, can’t be done if you are already doing a read without feeding the new read from somewhere other than stdin. Hence the < /dev/tty at that point in the script. So many strangers to thank for sharing their knowledge online. Thanks, strangers! That should do it.

Why this exists is I had a co-worker who added dates to tons of files in the format “01.02.03”, which resulted in files named “Example filename 01.02.03.xmpl” Same for phone numbers. Clearly this is wrong and something must be done about it (now that new ones won’t be cropping up since he.is.gone). You may be asking yourself how he got away with not getting an e-mailed file bounced back for multiple extensions? My educated guess is that he did and kept doing it the dumb way despite that.

Corrects the above format to “+%Y-%m-%d” (YYYY-MM-DD).

This could probably be done with fewer lines or overall be more betterer, but this is like my first whole shell script. Maybe my years of AppleScript are showing. *meh*
Continue reading

Zip droplet

This has been some hot garbage since I posted it. This is now actually not bad, but I can’t help but feel it’s clumsier than it could be. *meh*

Quick and dirty AppleScript droplet to zip files in the Finder.

-- http://strawhousepig.net/

-- This will not send files beginning with '.' (dot) to be zipped.

property def_loc : path to desktop
(*
If you're going to be sending zip archives to a location other than
a file-system domain (directories which the system has a 'nickname' for)
 I believe the above syntax would be:
	path to file "My HD:My Folder Daryl:My Other Folder Daryl:"
Or using POSIX style path
	path to POSIX file "/My HD/My Folder Daryl/My Other Folder Daryl/"
Although I am not sure about that. Another alternative would be to add an
if clause in the zip_it function to check for the "same" setting and then
use the container of item 1 of the files list "_it" as the default location.
*)

-- Not quite sure how to use this, in the AS routines or 'zip -x' or screw it and skip all files beginning with a dot?
--property no_can_zip : {".DS_Store", ".fseventsd", ".Spotlight-V100"}

on run
	tell application "Finder"
		set _it to selection as list
	end tell
	my zip_it(_it)
end run

on open _it
	zip_it(_it)
end open

on zip_it(_it)
	set _f to ""
	tell application "Finder" to set _dir to container of ((item 1 of _it) as alias)
	set my text item delimiters to {POSIX path of (_dir as alias)}
	repeat with i in _it
		if first character of name of (info for (i as alias)) is not "." then
			set _f to _f & " " & quoted form of text item 2 of (POSIX path of (i as alias))
		end if
	end repeat
	set the_c to count of _it
	if the_c > 1 then
		set z_name to (displayed name of (info for (item 1 of _it as alias))) & " + " & (the_c - 1) & " items.zip"
	else
		set z_name to (displayed name of (info for (item 1 of _it as alias))) & ".zip"
	end if
	set _z to (choose file name with prompt (the_c as string) & " item(s) to zip." default name z_name default location (_dir as alias))
	do shell script "cd " & quoted form of POSIX path of (_dir as alias) & " && zip  -ry " & quoted form of POSIX path of _z & _f
end zip_it

Parsing e-mail for info

[UPDATE] Added a version that works on OS X 10.4 to the bottom of this post. Does some different logging and is tighter, so I’ll have to go back to the original and update again.

This was done earlier, but I have since had to change it to match changes in the incoming data. Some of which is a big mystery. In particular a new line character that is input as the “line separator” Unicode character. It would end up in the clipboard as line feed, so I just started plugging in white space character id’s until one hit the mark. Lucky me.

Continue reading

Convert PDF to grayscale using GhostScript

[UPDATE] Huge caveat! While this is really meant to deal with RGB documents or objects, it does also convert CMYK and spot colors to grayscale. Unfortunately spot colors remain as separate plates that retain their name. This results in them being printed in color though on screen they appear gray. At least the colors (Pantone) and printer I tested on took spot channels and ripped them according to what they are named. If your printer does not have it’s own rendering library that matches your spot color names then I’m guessing they will print as grayscale.

It is possible to rasterize the art, which results in a pure grayscale, but you need such a high resolution even a simple business card with type and line art increases in size at least 30 times. I knew this was all too easy…

This script / app / droplet will convert a PDF or PostScript (.ps) document from whatever colorspace it lives in to grayscale. Has not been thoroughly tested. I mean, I ran it against a couple of files. One to work out the gs command, the other to test if it actually made a grayscale duplicate. That file was generated by MS Word so was of course RGB. The converted document was in fact true grayscale. I would say it converted to what you would get if you used a gray gamma 2.2 profile.

Continue reading

AppleTalk in the current year

If you’re anything like me and you have to print to an old AppleTalk printer, server, or RIP, -my condolences- keeping up-to-date and bridging that old connection becomes more difficult every decade. You are left with two choices; Keep an oldish Mac on hand capable of running Mac OS X 10.5 or earlier (a Power PC (PPC) is best in order to run the only browser using a modern cipher suite, TenFourFox [unfortunately development has ceased 🙁 ] from the brilliant and beautiful people at floodgap.com) or you can run an OS built on GNU+Linux, even as virtual machine, and have a fully modern desktop OS. Although in a VM a headless console will have a smaller footprint.

Continue reading

Convert PDF to JPEG using (old version of) Acrobat

This script will use Acrobat’s built in conversion settings (set in Acrobat’s preferences) to convert an open PDF to a new JPEG file and place that file in the folder of said PDF. If a file with the same name (including extension) exists it will prompt for a new name, at which point you may enter a new name or keep it the same and replace the old file.

Not allowing Acrobat to name the new file because, on Macintosh, Acrobat has a ridiculously low character limit when auto-generating a file.

Has not been tested with multi-page PDF’s, but I do not think it will handle them correctly [it does not]. Acrobat will do it, but the extra file shuffling will not. Also unknown if having a window (document) minimized will cause any shenanigans.

Also note this is written for Acrobat 7. Why? Because old hardware needs old software.

[UPDATE] Changed to allow multiple selections.

tell application "Adobe Acrobat 7.0 Professional"
try
set _docs to name of every document
if (count of _docs) is greater than 1 then
set _docs to (choose from list _docs with prompt "Select file(s) to convert:" with multiple selections allowed) as list
end if
repeat with i in _docs
set _doc to (every document whose name is i)
set _path to file alias of item 1 of _doc
set _temp to (path to temporary items folder as text) & "acrobat_tmp_jpg"
save item 1 of _doc to file _temp using conversion "com.adobe.acrobat.jpeg"
tell application "Finder"
set _name to (text items 1 thru -5 of i) & ".jpg"
set _proof to ((container of file _path) as text) & _name
if (exists _proof) then
set _name to text returned of (display dialog "File '" & _name & "' already exists. Please enter a new name (or leave the same to replace):" default answer _name as text)
set _proof to ((container of file _path) as text) & _name
end if
do shell script "mv " & quoted form of POSIX path of _temp & " " & quoted form of POSIX path of _proof
reveal file _proof
end tell
end repeat
end try
end tell

Speaking against the media narrative of motor vehicle collisions

As a once/sometime/hopefully again vehicular cyclist, a father, and a driver who tries to change my own attitude toward driving and motor vehicles, I consider myself part of the Crash Not Accident crowd. And this is my comment/rant on a recent article about a “truck getting into an accident with a pedestrian” (to paraphrase it).

Genericized and placed here for possible future use. This may be expanded on at some point.

Drivers don’t get cited because society gives us a pass. That’s starting to change but we need publications like this one to get on board. When describing a collision involving a motor vehicle do not attribute it to the vehicle. The truck didn’t hit the pedestrian, the driver did.

Also, drop the term “accident.” When an outside force is not involved these crashes and wrecks are *never* an accident. Faulty manufacturing, poor maintenance, and especially lack of due care while driving are all 100% preventable by a person making a better choice. The smoldering wreckage and broken bodies of a motor vehicle collision are consequences, not accidents.

Driving is by far the most dangerous thing most people will ever do. It’s past time to (once again) see it for what it is. Maybe then tens of thousands of people wouldn’t be killed year after year after year.

Video re-encode script

The purpose of this long, arduous venture was to find a way to simply reduce the size of video files recorded with a Canon ELPH 330 HS digicam. This camera, and surely others, records 720p, 30fps video at a bitrate of 24Mbps, which is at least twice as much as should be necessary. Remember this is a consumer level point-&-shoot whose main draws were: 10x optical zoom; pocketable. This high bitrate results in a 6 minute video being over 1GB. Too much.
Continue reading