rename part of folder name?

Hello, I have a download folder that has several folders inside that have names like 23-02-2013 or 01-10-2012 and I would like to change them all so they have names like 2013-02-23 or 2010-01-10 so that when I sort them by name they sort correctly. Can this be done with Applescript? And if so how?

Thanks in advance,
Vic

Model: imac
AppleScript: 2.2.3
Browser: Safari 536.26.17
Operating System: Mac OS X (10.8)

Yes, that would be straight forward in AppleScript. What have you got so far?

Hi,

Isn’t there something wrong in your post about the dates?

Probably I think. Something like this:


set f to choose folder -- download folder
tell application "Finder"
	set folder_list to every folder of f
	repeat with this_folder in folder_list
		set folder_name to name of this_folder
		tell (reverse of words of folder_name)
			set new_name to (item 1 & "-" & item 2 & "-" & item 3)
		end tell
		set name of this_folder to new_name
	end repeat
end tell

gl,

Model: MacBook Pro
AppleScript: 2.2.3
Browser: Safari 536.26.17
Operating System: Mac OS X (10.8)

I just thought of this, that I didn’t need the reverse.


set f to choose folder -- download folder
tell application "Finder"
	set folder_list to every folder of f
	repeat with this_folder in folder_list
		set folder_name to name of this_folder
		tell (words of folder_name)
			set new_name to (item 3 & "-" & item 2 & "-" & item 1)
		end tell
		set name of this_folder to new_name
	end repeat
end tell

Just reversed the order.

gl,

Or with an regular expression checking for the file name format first and before renaming the file check if the folder name already exists (downloaded before). It will give you a warning

set theFolder to POSIX path of (path to desktop folder)

set subFolders to every paragraph of (do shell script "ls -d " & quoted form of theFolder & "*/ | egrep -o '[0-9]{2}-[0-9]{2}-[0-9]{4}/' | cut -d / -f 1")
repeat with folderName in subFolders
	tell folderName to set newFolder to theFolder & word 3 & "-" & word 2 & "-" & word 1
	if (do shell script "[ ! -e " & quoted form of newFolder & " ] && mv " & quoted form of (theFolder & folderName) & space & quoted form of newFolder & " || echo no") = "no" then
		display alert "Folder '" & newFolder & "'already exists." as warning
	end if
end repeat

Here is my version on the subject:

A little function that utilizes awk, to rearrange the date. Probably adding any value, since the other solutions here are more complete, just showing an alternative.


set fn to "23-02-2013"
set nf to isodate for fn
log fn
--> 2013-02-23
to isodate for theDate
	set res to (do shell script "/usr/bin/awk 'BEGIN{FS=\"-\"}{print $3\"-\"$2\"-\"$1}'  <<<" & theDate)
	return res
end isodate

With pure Applescript you can really do it as simple as this:


set fn to "23-02-2013"
set nf to word 3 of fn & "-" & word 2 of fn & "-" & word 1 of fn
--> "2013-02-23"

Here we optimize a little bit for speed, since we make one reference to the filename, which we reference implicitly. This caters for that we don’t have to send the events the whole way every time we want something from fn.

set fn to "23-02-2013"
tell fn
	set nf to word 3 & "-" & word 2 & "-" & word 1
end tell
--> "2013-02-23"

We can even optimize this further, like kel1 did, so that we don’t have to scan fn for word’s more than once, cutting down on the number operations, which is always a good thing to do, as long as one remember that the number of bugs is proportional to the number of statements.

set fn to "23-02-2013"
tell (words of fn)
	set nf to item 3 & "-" & item 2 & "-" & item 1
end tell
--> "2013-02-23"

The terse version goes like this: Here we really do everything that we did before, but just in one line, we get the reversed list back, and lets Applescript assemble it for us by using text item delimiters. We set back the text item delimiters to their original value afterwards. This approach may be more inefficient than the one above, since we are using more assignements, but on the other hand we aren’t scanning for words. If one are to create new names for many folders, and keeps the statements that sets the text item delimiters outside that loop. Then this will be more efficient. Also: text items are more efficent in this case, since we are only looking for one delimiter, but splitting input into words, involves looking for many word-breaking characters, until we have the result set that consists of the list of words in the given input.


set fn to "23-02-2013"
set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, "-"}
set nf to reverse of (text items of fn) as text
set AppleScript's text item delimiters to tids
”> 2013-02-23

I think the absolutely fastest version would be as below: (when performing for many, and keeping the text item delimiters outside the loop).
Here we make Applescript assemble the parts of the new file name for us with the text item delimiter behind the scene, we don’t perform a list reversal, but address the elements directly.

set fn to "23-02-2013"
set {tids, text item delimiters} to {text item delimiters, "-"}
tell (text items of fn)
	set nf to {text item 3, text item 2, text item 1}'s text as text
end tell
set text item delimiters to tids
--> 2013-02-23

In context, the reversed names could all be manufactured by the same shell script which gets the originals:

set theFolder to POSIX path of (choose folder)

-- Alternating old and new names:
set oldAndNewNames to paragraphs of (do shell script ("ls -F " & quoted form of theFolder & " | sed -En 's|^([0-9]{2})(-[0-9]{2}-)([0-9]{4})/$|\\1\\2\\3\\'$'\\n''\\3\\2\\1|p'"))

-- Or: the old names, followed by the new in corresponding order:
set oldNamesAndNew to paragraphs of (do shell script ("ls -F " & quoted form of theFolder & " | sed -En '/^[0-9]{2}-[0-9]{2}-[0-9]{4}\\/$/ {s|/||p ; s|(..)(....)(....)|\\3\\2\\1| ; H ; } ; $ { g; s|^\\n||p ; }'"))

That is very nice indeed! :slight_smile:

I had an alternate solution in the same context, but it turned out to not be as simple as I hoped for as I can’t make “bracket-globs” work, or haven’t found the right incantation, yet. :mad:

This one tells if a folder with that date (name) exists already.


set APATH to "~/Downloads/"
set res to (do shell script "FS=\" \" ;cd " & APATH & "; for i in $(ls * |sed -n 's/^\\([0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]\\)[:]/\\1/p') ;
 do	 
    fn=$(echo $i |/usr/bin/awk 'BEGIN{FS=\"-\"}{printf(\"%4.4s-%2s-%2s\", $3,$2,$1)}')
    if test -e " & APATH & "$fn ; then 
        echo " & APATH & "$fn existed
        continue
    else
        mv " & APATH & "$i " & APATH & "$fn
			echo moved " & APATH & "$i to " & APATH & "$fn
    fi
 done

")
if res is "" then set res to "I found nothing to rename"
tell application "Finder"
	display dialog res
	
end tell

Back to the autotools… :expressionless:

I am obviously so . bored, in all the nuances of the word today hehehe. :slight_smile:

Here is another variation, I dissolve the parts of the filename on the command line, and makes them into arguments, that I then shuffle.

set dname to "23-12-2012"
set nf to(do shell script "set -- `echo " & dname & " |tr -s \"-\" \" \"`
echo $3-$2-$1")
log nf
”> "2012-12-23"

You should use a test -e like in mine because -d is not enough. The HFS file system doesn’t allow any kind (including directories) of files with the same name. Overwrite an empty text file with the same name as folder and your folder (including it’s content) is removed.

Hello.

Thanks for the correction.

I fixed the script above to use the -e switch for robustness. I can’t however see how I will be able to create a file that remove a directory, nor create a directory that removes a file,by using same names on the two. But the script is likely to crash, or at least malfunction during that iteration. And -e is more correct than -d. :slight_smile:

Edit

I have alisad mv to mv -i for my own comfort, so I would have had to issue something like command mv oldnm newnm
to get the functionality you describe. But I am still not able to do it. :expressionless:

6844$ touch 20-12-20 .. 6846$ mkdir 20-12-21 ... 6848$ command mv 20-12-21 20-12-20 mv: cannot overwrite non-directory ˜20-12-20' with directory ˜20-12-21'
[b]Ooops[/ºb]

I use GNU mv, that may explain it… I guess the normal behaviour is for mv to blatantly overwrite and existing file when you move something. So I’ll use test -e for the future, even if it is a directory I’ll move.

Thanks to all for your help. Got everything fixed.

Thanks again,
Vic

I had a real hard time figuring out something that would do something like your last example, but slightly simpler, as the input should go through sed line by line and be processed, without problems.

There is this things about line endings, but also that for some reason I cannot fathom at the moment, that the text needs to be quoted, and that every result gets back when you prey for paragraphs of the do shell script. There is some buffers here that aren’t flushed as they are supposed to I guess.

set fn to quoted form of "12-12-2012
14-12-2012"

-- can be a text  with one filename per line
set nf to paragraphs of (do shell script "tr -s '\\r' '\\n' <<<" & fn & "|sed  -En 's/^([[:digit:]]{2})-([[:digit:]]{2})-([[:digit:]]{4})/\\1-\\2-\\3	\\3-\\2-\\1/p'")
--> "12-12-2012	2012-12-12"

This works :), I guess you would have to coerce a list to quoted form of alist as paragraphs, to use it, ike this:

set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, linefeed}
set fn to quoted form of ({"12-12-2012", "14-12-2012"} as text) -- imposing the list with names from finder or similar
set AppleScript's text item delimiters to tids

Remember that it only works with commands that uses get line functions like sed. In other words the line separation is not done in bash but handled by sed. Bash-style would be quoted form of every line but not the line feed. I’m just saying to avoid confusing.

You are absolutely right, it is the quoted form that does the trick, and nothing else. But tr -s \r \n is needed if you don’t have linefeed as line-endings in the Script Editor I guess.

At least it worked now, without paragraphs of do shell script.

do shell script tr -s \r \n <<<" quoted form of somthing & " |. "

is a nice idiom for making it work whatever the settings of a script editor for line endings are.

When it comes to bash here documents as you described, I guess it is now way around the way of creating the text as you described, to ensure it works everywhere.

By the way: I recently come to know that “some versions of sed can only deal with here-documents with less than 12 lines.”

Edit

This idiom seems to work for variables feeding a do shell script at all times, regardless the line-endings (hopefully, as I can’t find a way to change the line-endings in Applescript Editor.)


set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, linefeed}
set fn to quoted form of ({"12-12-2012", "14-12-2012"} as text) -- imposing the list with names from finder or similar
set AppleScript's text item delimiters to tids

(below works)

set nf to paragraphs of (do shell script "sed  -En 's/^([[:digit:]]{2})-([[:digit:]]{2})-([[:digit:]]{4})/\\1-\\2-\\3\\
\\3-\\2-\\1/p' <<<" & fn)

What versions of sed cannot deal with more than 12 lines? I’m just going through the tutorial again.

I am not sure, but I have suspicions towards the one that is shipped with Apple. Not the one that GNU delivers. But it is just suspicions. The do shell script feels kind of flaky by itself, when it comes to here documents, which is the only place you’ll notice it.

When looking at Apple’s source code it’s number of lines are infinite.

Hello.

I’ll have a look too at my own leisure, my sed comes with a string named 2003 last compiled may the 18th 2009.
I said suspect, I wasn’nt definite, just said that some versions of said can’t handle more than 12 lines.

I take it you look at free BSD 4.4 sources?

On a general basis: Apple has updated at least some of the freeBSD frameworks in Mountain Lion, so that part is really going in the right direction. :slight_smile:

Edit

I’ll first test with here documents of different length, from bash. I’ll do it as soon as my autoconf macros work. :slight_smile:

Hello.

The version of sed that ships with Apple on Snow Leopard doesn’t do here documents at all, it does do script files, and I know that those can be longer than 12 lines. Well, here is what I meant, and it passed the test.
The bash script takes a paramater, that is the stemname of a to be header file, and produces and include guard, since I am tired of typing just that. :slight_smile:

[code]#!/bin/bash
/usr/bin/sed -n ’
s/…*/&/
h
g

1 i\

/*
s//&:/p
i
Created:‘“date +%m-%d-%Y”’
Author: McUsr

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

g
s/\./_/g
h
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
h
s/..*/_&_/
h
s/..*/#ifndef &/p
g
s/..*/#define &/p
i\

#endif
’ <<EOF
$1
EOF[/code]
By the way: via here you can find some of the earliest sources for the c-compiler.