Home > Back-end >  Use Automator to copy files to a new destination using a txt file with filenames, skip non existent
Use Automator to copy files to a new destination using a txt file with filenames, skip non existent

Time:09-17

Similar to the problem described here, I have a text file with filenames, and a folder with image files that need to be copied to another destination. As these are hundreds of files quite frequently, it would help a lot to automate this task.

The challenge is that some files in the text file might not exist, and the current version of the script I have can not account for this case and throws an error.

In summary, I would like to use Automator & Apple Script to:

  1. ask for a source folder with the original files
  2. ask for a destination folder where they should be copied to
  3. ask for a text file with the file names
  4. read the names from the text file
  5. [new] check if a matching file exists and copy it to the destination
  6. [new] if there is no matching file skip the line and move on to the next one

Here's what I have so far - this works as long as there is an actual image for every line in the text file:

Automator Actions

And AppleScript:

on run {input, parameters}
    
    set imgDestination to input's item 2
    set imgSource to input's item 1
    
    set imgNameFile to choose file with prompt {"Select file of image filenames:"}
    
    set imageList to every paragraph of (read imgNameFile)
    
    repeat with eachName in imageList
        tell application "Finder"
            set targetImageFile to item 1 of (get every file in folder imgSource whose name = (eachName as text))
            duplicate targetImageFile to folder imgDestination
        end tell
    end repeat
    return input
end run

Unfortunately my skills are not enough to come up with a if/else scenario for 5 & 6, so any help would be much appreciated.

CodePudding user response:

You have to check if the file exists.

Your script is quite inefficient because a whose clause in the Finder is very expensive although you could avoid the loop with

tell application "Finder"
    duplicate (get every file in folder imgSource whose name is in imageList) to folder imgDestination
end tell

A more efficient way is to retrieve the file names once and check if the list contains the current name.

There could be an unexpected behavior if the text file is UTF8 encoded which is a quasi standard. If so you have to read the text file as «class utf8».

Finally if the source and destination references in input are AppleScript alias specifiers you have to remove all occurrences of the folder keyword.

on run {input, parameters}
    
    set imgDestination to input's item 2
    set imgSource to input's item 1
    
    set imgNameFile to choose file with prompt {"Select file of image filenames:"}
    set imageList to every paragraph of (read imgNameFile as «class utf8»)
    
    tell application "Finder" to set fileNames to name of every file in folder imgSource
    
    repeat with eachName in imageList
        if fileNames contains eachName then
            tell application "Finder" to duplicate file eachName of folder imgSource to folder imgDestination
        end if
    end repeat
    return input
end run

CodePudding user response:

If the file is not found, the targetImageFile variable is set to {} (that is, an empty list). The error is thrown by the duplicate command because it cannot duplicate this empty list. The solution to the problem is: try to duplicate only when the targetImageFile value is not {}.

on run {input, parameters}
    
    set imgDestination to input's item 2
    set imgSource to input's item 1
    set imgNameFile to choose file with prompt {"Select file of image filenames:"}
    set imageList to paragraphs of (read imgNameFile)
    
    repeat with eachName in imageList
        tell application "Finder"
            set targetImageFile to (first file in folder imgSource whose name = eachName)
            if targetImageFile is not {} then duplicate targetImageFile to folder imgDestination
        end tell
    end repeat
    
    return input
end run
  • Related