Add a random number to the file's name let it be the unique one in the database

Hey folks, I’m sorry to bother you. I thought about this script all afternoon and didn’t understand why it crashed. I want to add a random number to the end of the files name to ensure that their names are unique. Here is my version.

tell application id "DNtp"
	set theRecord to the selection
	repeat with thisRecord in theRecord
		
		set thisDate to the creation date of thisRecord
		set thisYear to (((year in thisDate) as integer) - 2000) as string
		set thisMonth to ((month in thisDate) as integer) as string
		set thisDay to day in thisDate as string

		set theboolean to true
		repeat while theboolean is true
			set thisRandom to ((random number from 1000 to 9999) as string)
			set thisName to "F" & thisYear & thisMonth & thisDay & thisRandom
			set thisboolean to exists record with file thisName in database
		end repeat
		
		set the name of thisRecord to thisName
		
	end repeat
end tell

File name format: F + YYMMDD + random number
eg: F2010261234

It would be great if anyone can help me out, and hope that this will not take up too much time! thanks a lot!!

What does “crash” mean? Why not use a hash value instead of a (pseudo) random number? When will theBoolean ever become false? What happens if the selection contains more than one record?
Why is it important that filenames are unique?

Ha! If I can figure out these questions on my own, I might not ask this question… :pig: but it is indeed worth thinking about!

This is because, first, if there is a file with the same name in the folder, using a relative path to insert the media in markdown will make an error~ Second, I moved part of the content outside DT and indexed them to the database, and finder does not allow files with the same name in one folder, How to name them? emmm……I only thought of adding random numbers for them…

After I execute the script in DT, all the scripts in the script menu are grayed out. I guess this may be because my script has not stopped after running…

Sorry I really don’t know what this is… Let me search for it … hash value… :thinking:

My idea is to generate a random number. check if there is a file with the same name in the database. If there is, then generate a random number…until there is no one with the same name in the library… :sweat_smile:

I thought it meant that if there is such a file in the database, output true, otherwise the output of False may be my fault?

I suppose it has not even stopped running at all. See below.

I got that. It’s a classic pattern, albeit not a very good one. That’s why I mentioned hash values.
But please have a look at your code again and think about when our rather if theBoolean will ever become false. Look closely. And maybe think about using more helpful variable names then theType, too. What about exists, for example? A variable name should tell you something about the meaning or the use of it. Preferably at first glance.

I understand what you mean, the hash value may indeed be a better choice (although I still have a little knowledge after checking it on the Internet… :exploding_head:) emmm…I don’t know if my understanding is correct, but the hash value seems to be very long?

I think the problem should be here, but I tested this script in a newly created database. I feel that the probability of having the same name is very low. Why does the script keep running?

maybe

Did you read your code? Did you find the situation where theBoolean becames false? Are you sure that this is really happening at this place or do you just see what you want to see?

Again: Think about a different name for this variable.

(I don’t know if that’s better?? Also I’d like to ask how to debug in this situation, I’m testing on DT and if it keeps looping I’ll have to restart the software.)

tell application id "DNtp"
	set theRecord to the selection
	repeat with thisRecord in theRecord
		
		set thisDate to the creation date of thisRecord
		set thisYear to (((year in thisDate) as integer) - 2000) as string
		set thisMonth to ((month in thisDate) as integer) as string
		set thisDay to day in thisDate as string

		set theType to true
		repeat while theType is true
			set thisRandom to ((random number from 1000 to 9999) as string)
			set thisName to "F" & thisYear & thisMonth & thisDay & thisRandom
			if exists record with file thisName in database then
				set theType to true
			else 
				set theType to False
			end if
		end repeat
		
		set the name of thisRecord to thisName
		
	end repeat
end tell

Please: compare this

repeat while theboolean is true
with this
set thisboolean to exists …

It really jumps in my face, and you’d have seen it too if you had changed the variable’s name as I suggested already twice. I’m aware that prefixing names with “the” and “this” is very en vogue in AppleScript, but I still consider this mostbly not a good idea. First because all variables look the same at the start, which second takes more time to understand. And the third reason … very obvious here: You get confused yourself between all these “this”, “the”, “these”, “those”, “them” and “their”.

Oh my God it’s like I’m blind !!! No wonder I always get such bad grades in science.

Use script editor. If you’re going to do a lot of Apple Script scripting, get yourself Script Debugger, but that’s not free.
And: Your last version should work ok. At least it should not run till hell freezes over.
However: I’m not so sure that setting name of thisRecord is what you really want to do, given that you were talking about the file name before. AFAIK, the name of the record is not the same as the name of the file. But maybe they are identical for indexed files.

Since Script Debugger 7 there’s a free edition. Without this edition I wouldn’t recommend it to users who only want to write some scripts :slight_smile:

I always wondered if @BLUEFROG knows that there’s a free edition? I never understood why he doesn’t want new users to use Script Debugger, at least that’s what it seems to me.

I downloaded it and tested it out, and it does help me find out if I’m using undefined variables ~ looks like I’ll have to rely on it from now on.

Well, that’s what I already suggested some weeks ago … :slight_smile:

Thanks for that information. I wasn’t aware of that. I had downloaded it and assumed it would stop working after 30 days.

With @chrillek’s help you’ve found the mistake with the variable names.

But the script would still run forever because exists record with file expects a filename

… but you only pass variable thisName to it - without a suffix.

So you first need to get the suffix

tell application id "DNtp"
	try
		set theRecords to the selection of viewer window 1
		
		repeat with thisRecord in theRecords
			
			-- get the suffix ("exists record with file" checks the filename. if you let it check only for variable thisName it would run forever … )
			set thisFileName to filename of thisRecord
			set thisFileName_reverse to reverse of characters in thisFileName as string
			set thisSuffix to reverse of characters 1 thru ((offset of "." in thisFileName_reverse) - 1) in thisFileName_reverse as string
			if thisFileName = thisSuffix then set thisSuffix to ""
			
			set thisDate to the creation date of thisRecord
			set thisYear to (((year in thisDate) as integer) - 2000) as string
			set thisMonth to ((month in thisDate) as integer) as string
			set thisDay to day in thisDate as string
			
			set theDatabase to database of thisRecord
			
			set uniqueName to false
			repeat while uniqueName is false
				set thisRandom to ((random number from 1000 to 9999) as string)
				set thisName to "F" & thisYear & thisMonth & thisDay & thisRandom
				set uniqueName to (not (exists record with file ((thisName & "." & thisSuffix) as string)) in theDatabase)
			end repeat
			
			set the name of thisRecord to thisName
		end repeat
		
	on error error_message number error_number
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
		return
	end try
end tell

I always wondered if @BLUEFROG knows that there’s a free edition?

Yes, I’m aware of it.

I never understood why he doesn’t want new users to use Script Debugger, at least that’s what it seems to me.

It’s not required for AppleScripting. In fact, it’s a very complex tool for beginners. It’s also not built-in, i.e., another dependency.
Script Editor is simple, built-in, and has more than enough features for anyone to write scripts.

Oh! That’s a point I hadn’t thought of at all! Thanks to you!

Yes it does get a little complicated … for me, at least.

@cgrunenberg: What about a Current Date > Epoch Time placeholder for this or other purposes in Batch Process, etc.? This way it would be a unique value and could have some utility as well.