Tuesday, September 21, 2021

#1 2021-07-27 02:44:18 am

Eqe0509
Member
Registered: 2021-07-20
Posts: 2

Moving a file into a subdirectory, based on a partial string match?

Hey all, I've found myself working with applescript for about a month now. I'm working on a solution, but I can't seem to break through.

The solution will move a file, from a source directory, to a subfolder of a destination directory. The file and subfolder have partially matching names.

So, 3 important items:

-A file, with a naming format like this: "TV1001_JPartial_String_Match_Here_FILE_34059345.pdf"

-A source directory. The name of this is not relevant, as I'll just declare this folder, and not do anything else with it.

-A destination subdirectory, with a naming format like this:
"55555_JPartial_String_Match_Here_FOLDER_390489348". The file will be placed in the matching subdirectory.


So, moving into a specific directory, if there is a partial match. I've gotten a decent part of the way. Here is my current script.


Applescript:

property delim : "_"

set myStrings to ¬
   "TV1001_JPartial_String_Match_Here_FILE_34059345"

set strLength to count of characters of myStrings
set {TID, AppleScript's text item delimiters} to ¬
   {AppleScript's text item delimiters, delim}


set sTrim1 to text 9 thru (strLength + (offset of "J" in text)) of myStrings

set newStringsList to {}
repeat with thisString in paragraphs of sTrim1
   set delimCount to (length of text items of thisString) - 1
   if delimCount ≥ 3 then
       set thisString to text items 1 thru 4 of thisString
       set thisString to thisString as string
       copy thisString to end of newStringsList
   end if
end repeat

set AppleScript's text item delimiters to linefeed & linefeed
set myNewStrings to newStringsList as text
set AppleScript's text item delimiters to TID


set sourceDir to "~/Desktop/sourceDir"
set destDir to "~/Desktop/DestDir"
set subString to myNewStrings

do shell script "/usr/bin/find " & sourceDir & " -depth 1 -type d -name '*" & subString & "*' -exec mv {} " & destDir & " \\; "

display dialog myNewStrings

As you can see, I'm using a shell script to do the moving part, and finding the potential match before that.

Any ideas?


Filed under: applescript, files, Strings

Offline

 

#2 2021-07-27 08:04:05 am

Mockman
Member
From:: Toronto
Registered: 2020-05-27
Posts: 105

Re: Moving a file into a subdirectory, based on a partial string match?

You don't state what your actual issue is but three things come to mind.

First, if you are processing a single file, why have a repeat loop for the 'paragraphs'? There will only be a single paragraph (unless you have impossibly weird filenames, which doesn't seem to be the case). And why have paragraphs at all? Just work directly with the text.

For example…

Applescript:

set sTrim1 to "Partial_String_Match_Here_FILE_34059345" -- starting point based on prior code
set AppleScript's text item delimiters to "_"
set delimCount to (count of text items of (sTrim1 as text))
if delimCount is greater than 4 then
   set subString to text items 1 thru 4 of sTrim1
   subString as text
end if
--> Partial_String_Match_Here

You can further reduce the above code but it should be more clear this way.


Second, while the shell works with '~', applescript struggles with it (and often fails). So use something like this which will give you the posix path for the shell as well as make it easy to coerce into an alias:

set destDir to POSIX path of ((path to desktop as text) & "destDir:")
--> /Users/username/Desktop/destDir/
set destDira to POSIX file destDir as alias
--> alias "MacHD:Users:username:Desktop:destDir:"

FYI,there are other predetermined path locations (e.g. `path to home folder`). Now you can get your destination subdirectory with something like this:

Applescript:

set destDir to POSIX path of ((path to desktop as text) & "destDir:")
set destDira to POSIX file destDir as alias
tell application "Finder"
set destDirSubdirs to (every folder of destDira whose name contains "Partial_String_Match_Here")
set subDir to POSIX path of (item 1 of destDirSubdirs as alias)
end tell
--> /Users/username/Desktop/destDir/55555_JPartial_String_Match_Here_FOLDER_390489348/

Third, I'm not sure about the specific intent of the shell script. Is it to find the file to move or its destination subdirectory? If it is the latter, then you need to replace 'sourceDir' with 'DestDir' (as well as some other changes).

If it's the file to move, then why? You already have the file.

~/Desktop/sourceDir/TV1001_JPartial_String_Match_Here_FILE_34059345.pdf

You can just move it using applescript, like so:

Applescript:

set destDir to POSIX path of ((path to desktop as text) & "destDir:")
--> /Users/username/Desktop/destDir/
set destDira to POSIX file destDir as alias
--> alias "MacHD:Users:username:Desktop:destDir:"
set sourceDir to POSIX path of ((path to desktop as text) & "sourceDir:")
--> /Users/username/Desktop/sourceDir/
set sourceDira to POSIX file sourceDir as alias
--> alias "MacHD:Users:username:Desktop:sourceDir:"
set myStrings to "TV1001_JPartial_String_Match_Here_FILE_34059345"

set mPDF to (sourceDira & myStrings & ".pdf" as text) as alias

tell application "Finder"
   set destDirSubdir to (every folder of destDira whose name contains "Partial_String_Match_Here")
   set subDir to item 1 of destDirSubdir
   POSIX path of (subDir as alias)
   
   move mPDF to subDir
end tell

The above also gives you everything you need to build posix file references in case you want to use 'mv' in the shell.


Finally, if you want to use find/exec/mv for other reasons, your find command uses '-type d' which restricts the results to directories, so you won't find your pdf.

When I use the following in the terminal, it moves matching files to ~/Desktop/DestDir, but not to the subdirectory.
   

/usr/bin/find ~/Desktop/sourceDir -depth 1 -name '*Partial_String_Match_Here*' -exec mv {} ~/Desktop/destDir \;

Putting the applescript component aside for a moment, what terminal command will achieve your purposes? I find it easier to construct a 'do shell script' when the terminal command is known.


Filed under: shell

Offline

 

#3 2021-07-27 04:49:12 pm

Marc Anthony
Member
From:: Dallas, TX
Registered: 2006-04-27
Posts: 1039

Re: Moving a file into a subdirectory, based on a partial string match?

Hello, and welcome to forum. Most newbies aren't necessarily served by jumping straight into shell scripts. You may be able to use the Finder with a small file/folder quantity.

Applescript:

set fileList to {"TV1001_JPartial_String_Match_Here_FILE_34059345.pdf"} --assumedly more than one
set p2D to (path to desktop as text)
set {sourceFolder, destFolder} to {p2D & "sourceDir", p2D & "DestDir"}
tell application "Finder" to repeat with aFile in fileList
   move aFile to folder destFolder's folder 1 whose its name contains (aFile's (text ((my (offset of "_J" in aFile)) + 2) thru ((my (offset of "_FILE" in aFile)) - 1)))
end repeat

Offline

 

#4 2021-07-28 07:22:49 am

Eqe0509
Member
Registered: 2021-07-20
Posts: 2

Re: Moving a file into a subdirectory, based on a partial string match?

Thank you, Mark and Mockman. I was able to put together something I believe to be close to the result. Coming from OO-programming, I was having a hard time debugging.


Excuse the comments, I'm trying to get an overview of my script:

Applescript:

tell application "Finder"
   
   set selected to selection --Select source folder
   set current_folder to item 1 of selected --first item
   set mlist to every file of current_folder --folder as list
   set destDir to POSIX path of ((path to desktop as text) & "destDir:")
   --> /Users/username/Desktop/destDir/
   set destDira to POSIX file destDir as alias
   
   
   repeat with this_file in mlist --for each
       set cur_ext to name extension of this_file
       set strLength to count of characters of this_file
       set new_name to text 9 thru (strLength + (offset of "J" in text) - (length of cur_ext) + 2) of (name of this_file as text) --this is trimming
       
       set AppleScript's text item delimiters to "_"
       set delimCount to (count of text items of (new_name as text))
       if delimCount is greater than 4 then
           set subString to text items 1 thru 4 of new_name
           subString as text
       end if --Trim down to 3 underscores
       
       set myList to subString
       set saveTID to AppleScript's text item delimiters
       set FinalString to myList as text
       set AppleScript's text item delimiters to saveTID
       display dialog FinalString --Convert from list to string
       
       
       
       --Move file if folder contains trimmed string
       set destDirSubDir to (every folder of destDira whose name contains FinalString)
       
       if (name of destDirSubDir contains FinalString) then
           move this_file to destDirSubDir
       end if
       
   end repeat
end tell

It seems the script is 4 parts.
-1. Set up some files and folders, that I'll use later.
-2. Trim the string, remove up to the 3rd underscore. The string is now a list.
-3. Put the list into a string again.
-4. Move the file into a subdirectory, if new string is contained in name of any folders.


However, I get an error of error "Can’t get name of {}." number -1728 from name of {}, highlighting FinalString in the last if.

This seems like it tries to get the name of an empty array.

Offline

 

#5 2021-07-28 01:12:11 pm

Mockman
Member
From:: Toronto
Registered: 2020-05-27
Posts: 105

Re: Moving a file into a subdirectory, based on a partial string match?

Some major things…

strLength is trying to count a file object, and returns '0'. Instead, use 'set strLength to count of (get name of this_file)' which returns '51'.

Your 'set new_name' math confuses me. It is evaluating to…

text 9 thru (51 + 8 - 3 + 2), or text 9 thru 58, but your filename isn't that long.


Can you provide what 'new_name' should be after this? I'm guessing that you can just leave out either the 'text 9' or the offset. So 'set new_name to text 9 thru ((length of (get name of this_file)) - (length of cur_ext) - 1) of (get name of this_file)' captures 'Partial_String_Match_Here_FILE_34059345' or text 9 thru 47.

Alternatively, you can specify the last character of a string (character 51 or 'f') with '-1'. The '5' next to the extension (character 47) is -5. So 'text 9 thru -5' would capture 'Partial_String_Match_Here_FILE_34059345'.

Repeat loop… if you're only going to have a single file selected, then you don't need to use repeat. Just use… 'set this_file to item 1 of mlist'. But if you want the script to move multiple files, then you need to make other changes.

Finally, the empty list error you refer to results from asking the 'name of destDirSubDir', instead of asking the folder's name. Instead, ask 'if name of (item 1 of destDirSubDir)' contains that string. Then, 'move this_file to item 1 of destDirSubDir'.


Applescript:

tell application "Finder"
   
   set selected to selection --Select source folder
   set current_folder to item 1 of selected --first item
   set mlist to every file of current_folder --folder as list
   -- set destDir to POSIX path of ((path to desktop as text) & "destDir:")
   -- tell me to set destDira to POSIX file destDir as alias
   set destDira to ((path to desktop) as text) & "destDir:" as alias
--> alias "MacHD:Users:username:Desktop:destDir:"

   repeat with this_file in mlist --for each
       set cur_ext to name extension of this_file
       set strLength to length of (get name of this_file)
       set new_name to text 9 thru ((length of (get name of this_file)) - (length of cur_ext) - 1) of (get name of this_file)
       --> Partial_String_Match_Here_FILE_34059345
   end repeat
   
   set AppleScript's text item delimiters to "_"
   set delimCount to (count of text items of new_name)
   if delimCount is greater than 4 then
       set subString to text items 1 thru 4 of new_name
   end if --Trim down to 3 underscores
   
   set FinalString to subString as text
   display dialog FinalString --Convert from list to string
   -- Partial_String_Match_Here
   
   --Move file if folder contains trimmed string
   set destDirSubDir to (every folder of destDira whose name contains FinalString)
   
   if name of (item 1 of destDirSubDir) contains FinalString then
       move this_file to item 1 of destDirSubDir
   end if
end tell

And a few comments…

In general, you can get the count (or its synonym 'length') of 'text' or 'characters'. As the file name is text, you can forego getting its characters to determine strLength.

'name of' returns text so 'as text' is redundant in 'name of this_file as text'

saveTID: It doesn't harm this script but the 'set saveTID' should be set at the beginning of the script (or anywhere before you first set them to '_').

You can do without 'mylist'. Optionally, you can do without 'FinalString' as well (e.g. 'set subString to subString as text').

Posix file: If you use it straight up inside an application tell block it generates a silent error. Preface it with 'tell me to' or move it outside the tell block.

And actually, if you don't have a specific need for posix (i.e. for use in the shell) then you can skip that step:

    -- set destDir to POSIX path of ((path to desktop as text) & "destDir:")
    -- tell me to set destDira to POSIX file destDir as alias
    set destDira to ((path to desktop) as text) & "destDir:" as alias

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)