{"id":915,"date":"2021-02-03T17:02:17","date_gmt":"2021-02-04T00:02:17","guid":{"rendered":"http:\/\/10.0.1.201\/?p=915"},"modified":"2025-11-30T12:23:32","modified_gmt":"2025-11-30T19:23:32","slug":"script-to-re-write-dates-in-file-names","status":"publish","type":"post","link":"https:\/\/strawhousepig.net\/wordpress\/2021\/02\/03\/script-to-re-write-dates-in-file-names\/","title":{"rendered":"Script to re-write dates in file names"},"content":{"rendered":"<p>Annnnnd I&#8217;m done.<\/p>\n<p><ins datetime=\"2021-02-05T05:32:36+00:00\">Did I say &#8220;done?&#8221; 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&#8230; or at least that&#8217;s the idea. Unsure if working at this time. I don&#8217;t believe it do. Only if `date` can&#8217;t reformat the string it&#8217;s fed will it be able to notice, but that is printed to stdout already. It&#8217;s the &#8220;Warning:&#8221; lines that are ambiguous.<\/ins><\/p>\n<p>Removed the &#8220;error checking&#8221; which didn&#8217;t work. I suggest making note of any errors reported to stdout while the script runs.<\/p>\n<p>The main extended regex that matches the mm.dd.(yy)yy pattern is now a variable.<\/p>\n<pre>#!\/bin\/sh\n# http:\/\/strawhousepig.net\/\n\n# The following `egrep` (or `grep -E`) should prove useful when checking the\n# storage file. If your text editor supports grep based 'find all' you\n# may be able to highlight the original text that is to be changed.\n# egrep -nv '(1[0-2]|0?[1-9])[.-\/,]([0-2]?[1-9]|[1-3][0-1])[.-\/,](20)?[0-9]{2}(\\.[[:alnum:]]+)?[[:space:]]\/'\n\n# Name of file in which to store 'mv' statements.\nmvstore=\"mvstore.sh\"\n\n# The number of parentheses here affects the `sed` for $e. Currently \"\\4\".\ndateregex=\"(1[0-2]|0?[1-9])[.-\/,]([0-2]?[1-9]|[1-3][0-1])[.-\/,](20)?[0-9]{2}\"\n\nusage=\"\nThis script looks recursively for the date pattern mm.dd.yy and similar\nin file and directory names beginning at 'pwd'. It then generates an 'mv'\nstatement for each item with the pattern re-written by 'sed' &amp; 'date'\nto yyyy-mm-dd.\n\nRunning the '-e' option without first creating and checking the storage\nfile is not recommended.\n\n-w Write the 'mv' statements to the file '$mvstore'\nin the present working directory.\n-e Evaluate the 'mv' statements as they are generated.\n-h Displays this helpful text.\n\\n\"\n\nfunction mvdatef() {\n# Here, 'tail' reverses the order of 'find' after 'egrep' filters the result.\n# That way files in a directory are renamed before the directory is.\n# 'find' might be able to use the regex, but I couldn't work it out. YMMV.\n# This only looks for the pattern at the end of the line or just before an extension.\n# If something isn't working, the regex here is probably where it started.\nfind \"`pwd`\" | egrep '[\/[:space:]]'\"$dateregex\"'(\\.[[:alnum:]]+)?$' | tail -r | while read a\ndo\n\n# Escape certain characters so they don't wreck the 'mv' statement later.\n# double quote, single quote, parens, ampersand, dollar sign, and space.\n# Single quote, parens, and ampersand are escaped for the shell after breaking out of the 'sed' statement.\nb=$(echo \"$a\" | sed -E 's\/([\"'\\'\\(\\)\\&amp;'[:space:]$])\/\\\\\\1\/g')\nif [ \"$b\" == \"\" ]; then\necho \"Error: Could not escape $a\" &gt;&gt; $mvstore\nfi\n# Suck out the last instance of our hated date pattern (00.00.00 or 00.00.0000).\n# Also replace dashes, slashes (not working :| ), and errant commas for dots\n# because we've come too far not to.\nc=$(echo \"$a\" | egrep -o \"$dateregex\" | tail -1 | sed -E 's\/[-\/,]\/\\.\/g')\nif [ \"$c\" != \"\" ]; then\n# 'date' will not accept a 2 OR 4 digit year.\nif [ $(echo $c | egrep -o \"[0-9]{4}$\") ]; then\ndform=\"%m.%d.%Y\"; else\ndform=\"%m.%d.%y\"\nfi\nd=\"$(date -j -f \"$dform\" \"$c\" \"+%Y-%m-%d\")\"\nif [ \"$d\" == \"\" ]; then\necho \"Error: Could not format date from $c\" &gt;&gt; $mvstore\nfi\n# This is the 'sed' that finds the date and replaces it with what we made just above.\n# It looks for the pattern at the end of the line (path) but includes the extension if there.\n# It is possible that a version number of some sort will also match.\n# Also possible to do away with the EOL in the regex and just go for the pattern.\ne=\"$(echo \"$b\" | sed -E 's\/'\"$dateregex\"'(\\.[[:alnum:]]+)?$\/'$d'\\4\/')\"\nif [ \"$e\" == \"\" ]; then\necho \"Error: Could not replace $c in $a\" &gt;&gt; $mvstore\nfi\n# After all that dicking around, this is the mv statement.\nf=\"mv -- $b $e\"\n\nif [ $1 ]; then\neval $f\nelse\necho \"$f\" &gt;&gt; \"$mvstore\"\nfi\nelse\necho \"Error: $c - Could not pull viable date from $b\" &gt;&gt; $mvstore\nfi\ndone\n}\n\nif [[ $1 = \"-h\" ]] ; then\nprintf \"$usage\"\nexit\nelif [[ $1 = \"-e\" ]]; then\necho \"Evaluating 'mv' statements as they are generated...\"\nmvdatef -e\nelif [[ $1 = \"-w\" ]]; then\necho \"Generating file `pwd`\/$mvstore and writing 'mv' statements to it...\"\nprintf \"#\/bin\/sh\\n# `date`\\n\" &gt; \"$mvstore\"\nmvdatef\nelse\nprintf \"$usage\"\nexit\nfi<\/pre>\n<p>Original, less-good version: <a href=\"http:\/\/strawhousepig.net\/shell-script-to-re-format-poor-date-format-in-filenames\/\">http:\/\/strawhousepig.net\/shell-script-to-re-format-poor-date-format-in-filenames\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Annnnnd I&#8217;m done. Did I say &#8220;done?&#8221; 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&#8230; or at least that&#8217;s the idea. Unsure if working at this time. I don&#8217;t believe it do. Only [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[18,24,28,33,34],"class_list":["post-915","post","type-post","status-publish","format-standard","hentry","category-code","tag-gnulinux","tag-macos","tag-os-x","tag-script","tag-shell-script"],"_links":{"self":[{"href":"https:\/\/strawhousepig.net\/wordpress\/wp-json\/wp\/v2\/posts\/915","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/strawhousepig.net\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/strawhousepig.net\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/strawhousepig.net\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/strawhousepig.net\/wordpress\/wp-json\/wp\/v2\/comments?post=915"}],"version-history":[{"count":1,"href":"https:\/\/strawhousepig.net\/wordpress\/wp-json\/wp\/v2\/posts\/915\/revisions"}],"predecessor-version":[{"id":1059,"href":"https:\/\/strawhousepig.net\/wordpress\/wp-json\/wp\/v2\/posts\/915\/revisions\/1059"}],"wp:attachment":[{"href":"https:\/\/strawhousepig.net\/wordpress\/wp-json\/wp\/v2\/media?parent=915"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/strawhousepig.net\/wordpress\/wp-json\/wp\/v2\/categories?post=915"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/strawhousepig.net\/wordpress\/wp-json\/wp\/v2\/tags?post=915"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}