Need Help with a special "Leading zeros"

Hello Guys,

I have been exploring this site for ages…
And I Love It :slight_smile:
You guys have always supply answer with out me asking any question… :wink:

But now I’m stuck in a jam and I need help
Yes I have search and search and search but nothing works in what I’m trying to do
So please HELP and thank you very very very much in advance…

Q? : I’m creating Applescript that go’s to get files and rename theme a special way…

Here’s a example of what I have :

WBHregu20130527 1.pdf
WBHregu20130527 2.pdf
WBHregu20130527 39.pdf
WBHregu20130527 148.pdf

and I need to rename theme like this :

wbh0regu20130527001.pdf
wbh0regu20130527002.pdf
wbh0regu20130527039.pdf
wbh0regu20130527148.pdf

Ok…

For so far I manage to change the “WBH” for “wbh0”

But I can’t find a way to get rid of the space and stick the page number with a leading of 3 digits in all
[from this “…27 1.pdf” to this "…27001.pdf’] or [from this “…27 39.pdf” to this "…27039.pdf’] or [from this “…27 148.pdf” to this "…27148.pdf’]

I’m all ready using this for the rename of the “WBH” to “wbh0”



try
	tell application "Finder" to set the source_folder to folder ("wbh0regu" & datadate2) of folder "beloeil_WBH" of folder datadate2 of folder "BAC_MONTEREGIE" of folder "JeqProd" of disk "InnografW" as alias
end try

set the search_parameter to the "File Names"
set the search_string to the "WBH"
set the replacement_string to the "wbh0"

set the item_list to list folder source_folder without invisibles
set source_folder to source_folder as string
repeat with i from 1 to number of items in the item_list
	set this_item to item i of the item_list
	set this_item to (source_folder & this_item) as alias
	set this_info to info for this_item
	set the current_name to the name of this_info
	set change_flag to false
	if the current_name contains the search_string then
		if the search_parameter is "File Names" and ¬
			folder of this_info is false then
			set the change_flag to true
		end if
		if the change_flag is true then
			-- replace target string using delimiters
			set AppleScript's text item delimiters to the search_string
			set the text_item_list to every text item of the current_name
			set AppleScript's text item delimiters to the replacement_string
			set the new_item_name to the text_item_list as string
			set AppleScript's text item delimiters to ""
			my set_item_name_wbh_B(this_item, new_item_name)
		end if
	end if
end repeat

on set_item_name_wbh_B(this_item, new_item_name)
	tell application "Finder"
		--activate
		set the parent_container_path to (the container of this_item) as text
		if not (exists item (the parent_container_path & new_item_name)) then
			try
				set the name of this_item to new_item_name
			on error the error_message number the error_number
				if the error_number is -59 then
					set the error_message to "This name contains improper characters, such as a colon (:)."
				else --the suggested name is too long
					set the error_message to error_message -- "The name is more than 31 characters long."
				end if
				tell me to display dialog the error_message default answer new_item_name buttons {"Cancel", "Skip", "OK"} default button 3
				copy the result as list to {new_item_name, button_pressed}
				if the button_pressed is "Skip" then return 0
				my set_item_name_wbh_B(this_item, new_item_name)
			end try
		end if
	end tell
end set_item_name_wbh_B


Any other suggestion to even make this script shorter be appreciated… Because I have over 80 kings of “WBH” “WBR” “WCG” and so on…

Thank you again for ANY HELP

Joel St-Onge
joelstonge@mac.com

something like this maybe?

set theList to {"27 1.pdf", "27 39.pdf", "27 148.pdf"}
repeat with theItem in theList
	set contents of theItem to word 1 of theItem & text -3 thru -1 of ("000" & word 2 of theItem) & "." & word 3 of theItem
end repeat
return theList

edit: an complete solution would look like

set theList to {"WBHregu20130527 1.pdf", "WBHregu20130527 2.pdf", "WBHregu20130527 39.pdf", "WBHregu20130527 148.pdf"}
repeat with theItem in theList
	set contents of theItem to "wbh0" & text 4 thru -1 of word 1 of theItem & text -3 thru -1 of ("000" & word 2 of theItem) & "." & word 3 of theItem
end repeat
return theList

Hey Joel,

This is a job for the superhero of text processing - regular expressions. I’ve done the job the easy way with the Satimage.osax:

set _sample to paragraphs of text 2 thru -2 of "
WBHregu20130527 1.pdf
WBHregu20130527 2.pdf
WBHregu20130527 39.pdf
WBHregu20130527 148.pdf
"
set textList to change "^([A-Z]+)" into "\\l\\10" in _sample with regexp
repeat with i in textList
	set _num to find text " (\\d+)\\.\\w{3}$" in (contents of i) using "\\1" with regexp and string result
	set _num to format _num into "000"
	set contents of i to change " (\\d+)\\.\\w{3}$" into _num in (contents of i) with regexp
end repeat
textList

But it could be done with Shane’s ASObjC_Runner, sed, awk, Perl, etc.

Edit:

I used a loop to simulate renaming a selection of files.

There’s also the problem of padding an uncertain number: WBHregu20130527 148.pdf

Could ‘148’ be ‘10148’? What is the upper limit?

Until Nigel chimes in …here is another option:


set fileName to "WBHregu20130527 39"

set newName to do shell script "sed -E ' {
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ 
s/(^[a-z]{3})/\\10/
s/.pdf$//
s/ ([0-9]+)/ 000\\1/
s/ 0*([0-9]{3,})/\\1.pdf/
} ' <<< " & quoted form of fileName


Then it’s not clear to me why you’re using an repeat loop. I would say that only the power of regex will truly come alive when processing multiple lines at once, like in adayzdone code. Now you’re using 2 Apple Events for only the first 3 characters and add leading zeros, AppleScript is perfectly able to do that without any help without the cost of Apple Events and easier coding too :).

here an version with AWK using no regular expression but changes multiple lines:

set theFiles to "WBHregu20130527 1.pdf
WBHregu20130527 2.pdf
WBHregu20130527 39.pdf
WBHregu20130527 148.pdf"

set newFiles to do shell script "awk '{printf \"wbh0%s%03d.pdf\\n\", substr($1, 4), $2}'<<<" & quoted form of theFiles

return every paragraph of newFiles

Ok Guys…

Thank you in advance…

But All your script work swell in applescript

But when I run it in in computer with the files… this :



tell application "Finder"
	(*
	repeat
	display dialog "Entrer la date SANS LES TIRETS S.V.P. (JJMMMAAAA)" default answer "" buttons {"Cancel", "OK"} default button 2
	set the jourdate to the text returned of the result
	if the jourdate is not "" then exit repeat
	end repeat
	*)
	repeat
		display dialog "Entrer la date AVEC LES TIRETS S.V.P. (AAAA-MM-JJ)" default answer "" buttons {"Cancel", "OK"} default button 2
		set the datadate to the text returned of the result
		if the datadate is not "" then exit repeat
	end repeat
end tell

(* END Get Datadate *)

(* datadate2 Remove "-" *)

RemoveFromString(datadate, "-")

on RemoveFromString(theText, CharOrString)
	-- ljr (http://applescript.bratis-lover.net/library/string/)
	local ASTID, theText, CharOrString, lst
	set ASTID to AppleScript's text item delimiters
	try
		considering case
			if theText does not contain CharOrString then ¬
				return theText
			set AppleScript's text item delimiters to CharOrString
			set lst to theText's text items
		end considering
		set AppleScript's text item delimiters to ASTID
		return lst as text
	on error eMsg number eNum
		set AppleScript's text item delimiters to ASTID
		error "Can't RemoveFromString: " & eMsg number eNum
	end try
end RemoveFromString

set the datadate2 to the result

(* END datadate2 Remove "-" *)



(* WBH *)

tell application "Finder"
	
	set the theFiles to every file of folder ("wbh0regu" & datadate2) of folder "beloeil_WBH" of folder datadate2 of folder "BAC_MONTEREGIE" of folder "JeqProd" of disk "InnografW"
	
	set newFiles to do shell script "awk '{printf \"wbh0%s%03d.pdf\\n\", substr($1, 4), $2}'<<<" & quoted form of theFiles
	
	return every paragraph of newFiles
	
end tell


It Does not do it and it returns me this :

Help :frowning:

I am so clost…

Hey Joel,

Okay; this code actually works on a Finder selection:

on FMT(_num) # Work around the Finder's dislike of SIO's 'format' command.
	format _num into "000"
end FMT
tell application "Finder"
	set fileList to selection as alias list
	if fileList ≠ {} then
		repeat with i in fileList
			set fileName to name of i
			set newName to change "^([A-Z]+)" into "\\l\\10" in fileName with regexp
			set _num to find text " (\\d+)\\.\\w{3}$" in newName using "\\1" with regexp and string result
			set _num to FMT(_num) of me
			set newName to change " \\d+(\\.\\w{3}$)" into _num & "\\1" in newName with regexp
			if fileName ≠ newName then
				set name of i to newName
			end if
		end repeat
	end if
end tell

It is dependent upon the Satimage.osax.

I used a loop to try to make the process more comprehensible and since one would be necessary in the rename process anyway.

For my own use I’d get all the names in a list, do the renames en mass, and then process through with the matched name/file lists.

Well that’s one approach, but it’s not the only one. DJ’s vanilla suggestion is a good one, although I don’t think he got the case-change right for the first three characters; I think he assumed they wouldn’t change.

Anyway, here’s another approach that doesn’t use regular expressions. You will have to save it as a Cocoa-AppleScript app from ASE, or run it from ASObjC Runner. But it’s vanilla, and regex-free :slight_smile:

set theSample to current application's NSString's stringWithString_("WBHregu20130527 1.pdf
WBHregu20130527 2.pdf
WBHregu20130527 39.pdf
WBHregu20130527 148.pdf
WBHregu20130527 1.pdf
")
-- make formatter
set theFormatter to current application's NSNumberFormatter's new()
theFormatter's setFormat_("000")
-- make char set
set capSet to current application's NSCharacterSet's uppercaseLetterCharacterSet()

-- make final array
set theArray to current application's NSMutableArray's arrayWithCapacity_(100)
-- make a scanner
set theScanner to current application's NSScanner's scannerWithString_(theSample)
repeat
	-- get uppercase chars
	set {theResult, firstString} to theScanner's scanCharactersFromSet_intoString_(capSet, reference)
	if theResult as boolean = false then exit repeat
	-- get rest up to space
	set {theResult, nextString} to theScanner's scanUpToString_intoString_(space, reference)
	-- get integer, format with leading zeros
	set {theResult, theInt} to theScanner's scanInt_(reference)
	set intString to theFormatter's stringFromNumber_(theInt)
	-- get the rest of the string
	set {theResult, lastString} to theScanner's scanUpToString_intoString_(linefeed, reference)
	-- make single string and add to array
	tell current application's NSString to set oneResult to stringWithFormat_("%@0%@%@%@", firstString's lowercaseString(), nextString, intString, lastString)
	theArray's addObject_(oneResult)
end repeat
return theArray as list

Not quite as fast as regex, but still no slouch. And hey, it’s almost readable :wink:

Hi.

That’s because you’re trying to get the ‘quoted form’ of a list of Finder references. ‘quoted form’ is for text. In your case, the text you’ll need is the names of the files.

Here’s an example using another regex possibility: sed.

tell application "Finder"
	set targetFolder to folder ("wbh0regu" & datadate2) of folder "beloeil_WBH" of folder datadate2 of folder "BAC_MONTEREGIE" of folder "JeqProd" of disk "InnografW"
	set originalNames to name of every file of targetFolder
end tell

-- Get all the names as a single piece of text with linefeed delimiters.
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to linefeed
set origNamesAsTxt to originalNames as text
set AppleScript's text item delimiters to astid

set editedNames to paragraphs of (do shell script ("<<<" & quoted form of origNamesAsTxt & " sed -E '
/^[A-Z]+[a-z]+[0-9]+ [0-9]+\\.pdf$/ {
	s/^[A-Z]+/&0/
	y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
	s/ ([0-9]{3})/\\1/
	s/ ([0-9]{2})/0\\1/
	s/ /00/
}'"))

repeat with i from 1 to (count originalNames)
	set oldName to item i of originalNames
	set newName to item i of editedNames
	if (newName is not oldName) then
		tell application "Finder" to set name of file oldName of targetFolder to newName
	end if
end repeat

Edit: Revamped in the light of Shane’s comment immediately below.

Nigel, I think you missed this part of the original post:

I suspect he meant kinds, meaning the first three characters are caps but can vary.

Yes I did. Thanks, Shane. I also overlooked adaydone’s post. :confused:

I’ve now adjusted my script to catch different kin[gd]s, taking the transition from upper to lower case as their end boundaries.

And then some vanilla vanilla…

set naam to "WBHregu20130527 1.pdf"

set AppleScript's text item delimiters to "regu"
set naamList to text items of naam --> {"WBH", "20130527 1.pdf"}
set AppleScript's text item delimiters to ""

-- this turns text into a list of numbers
set idList to (id of item 1 of naamList) -- "WBH" becomes {87, 68, 72}
-- note: this is the range of possible values, assuming that only characters are used, no numbers or punctuation
id of "A" -- 65
id of "Z" -- 90
id of "a" -- 97
id of "z" -- 122

-- now we'll do some simple math to go from uppercase to lowercase
set charCount to count idList
repeat with i from 1 to charCount
	if item i of idList < 97 then set item i of idList to (item i of idList) + 32 -- 97-65
end repeat
-- turn the list of numbers back into text, and append required zero
set item 1 of naamList to string id idList & "0"

-- and do the other thing
set AppleScript's text item delimiters to "regu"
set naam to (text items of naamList) as text
set AppleScript's text item delimiters to space
set naamList to text items of naam
set AppleScript's text item delimiters to ""

set item 2 of naamList to text -7 thru end of ("000" & item 2 of naamList) as text
set naam to naamList as text

adyzdone’s solution takes 10-20 msec here; this one under 0.5 msec.
Only drawback I can think of is that this is strictly dependent on the given name structure.
I suspect awk versions, and others, can be made to work with changing patterns without adding much overhead.

I assume that’s for one name. I suspect the regex-based solutions will scale better.