Check file name for range of characters - applescript

Is there a way to tell Applescript to locate a file where the file name would match this type of criteria:
set foundFile to file whose name starts with
[character 0-9] followed by [character 0-9] followed by underscore

I can't think of a way to do it with a Finder whose clause statement. However grep has regular expression capabilities so try this...
set theFolder to choose folder
set foundFileNames to paragraphs of (do shell script "ls " & quoted form of POSIX path of theFolder & " | grep '^[0-9][0-9]_'")
set firstFoundFile to (theFolder as text) & item 1 of foundFileNames

Here's a handler that does this with all Applescript and no shell script.
-- get your folder however and feed the folder to the handler getMatchingFiles(*your folder*)
on getMatchingFiles(theFolder)
tell application "Finder"
set theFiles to every file of theFolder
set allDigits to "0123456789"
set matchingFiles to {}
repeat with aFile in theFiles
set fileName to the name of aFile
if ((the first character of fileName is in allDigits) and (the second character of fileName is in allDigits) and (the third character of fileName is "_")) then copy aFile to the end of matchingFiles
end repeat
end tell
return matchingFiles
end getMatchingFiles

regulus6633's answer is promising, but there's no need to resort to resort to external utilities ls and grep; the shell's own pathname expansion (globbing) is sufficient, using pattern [0-9][0-9]_*:
# Pick a folder.
set targetFolder to choose folder
# Get matching files.
# `shopt -s nullglob` instructs the shell to return an empty string, if no files match.
set foundFiles to paragraphs of (do shell script "shopt -s nullglob; printf '%s
' " & quoted form of POSIX path of targetFolder & "[0-9][0-9]_*")
# Extract the 1st matching file.
set foundFile to item 1 of foundFiles

Related

Play sound with AppleScript using afplay and relative file path

I'm trying to create an AppleScript that uses afplay (as suggested here) to play a random sound file that's located in a directory within the same directory as the script.
folder
-- applescript.scpt
-- sounds
----- sound-x.aiff
I found this comment regarding relative paths to be potentially useful:
(POSIX path of (path to me))
However, I keep receiving errors when I try mashing it up with this approach for randomness...
set theNumber to 3
set theFiles to {}
repeat
set file_path to quoted form of (POSIX path of (path to me))
tell application "Finder" to set aFile to (some file of file_path & "/sounds_dir") as text
if aFile is not in theFiles then
set end of theFiles to aFile
tell application "Finder" to open file aFile
do shell script ("afplay " & file_path & " > /dev/null 2>&1 &")
end if
if (count of theFiles) is equal to theNumber then exit repeat
end repeat
In a script, path to me returns the path to the script file but we need its parent path to add a sub path.
To compose the correct path, we can use the subroutine composeFilePath(fileName).
The main action is in the repeat loop. I also added a delay so it's easier to test. Save the script before using since path to me will return a wrong path when its unsaved.
set LOOPS to 3
set soundFolderName to "sounds_dir"
# ---------------------
# SETUP
# ---------------------
set soundFolderFullPath to my composeFilePath(soundFolderName)
tell application "Finder"
if folder soundFolderFullPath exists then
set soundFolder to (folder soundFolderFullPath)
else
set soundFolder to ""
# Customize action when folder does not exist
beep
log "*** Error: folder " & quoted form of soundFolderFullPath & " missing!"
return
end if
if (count files in soundFolder) is 0 then
# Customize action when folder has no items in it
beep
log "*** Error: No items in " & quoted form of soundFolderFullPath & " !"
return
end if
end tell
# -------------------------------------------
# We have "soundFolder" and it has items in it
# -------------------------------------------
repeat LOOPS times
# PLAY RANDOM FILE
# As ONE LINER:
## do shell script "/usr/bin/afplay " & quoted form of (POSIX path of ((some file of soundFolder) as text)) & " > /dev/null 2>&1 &"
# Step By Step
set aRandomFile to some file of soundFolder
set aRandomFile to POSIX path of (aRandomFile as text)
set shellScript to "/usr/bin/afplay " & quoted form of aRandomFile & " > /dev/null 2>&1 &"
do shell script shellScript
delay 1
end repeat
on composeFilePath(fileName)
if fileName is "" then return ""
set pathToMe to path to me -- this is the full path to this script
-- get the folder this script is in:
set thisScriptsFolder to ""
tell application "Finder"
try
set thisScriptsFolder to (get container of pathToMe) as text
end try
end tell
if thisScriptsFolder is "" then
return ""
end if
return thisScriptsFolder & fileName -- full path
end composeFilePath
You have your paths all messed up. Applescript doesn't use "posix paths" so you can't pass that type of path to applications such as the Finder. Shell scripts do use posix paths and you have to quote them.
In addition for applescript, whenever your path is in string format you must put the word "file" or "folder" in front of the path before you use it so that applescript can understand it's an object to be acted upon otherwise applescript just treats it like a string. Also string paths in applescript should be colon delimited (:) rather than slash delimited (/). Finally applescript paths start with the name of your hard drive such as "Macintosh HD".
You can see you must treat paths in applescript much differently than you do with the shell. Anyway, I didn't test this code but using those basic rules this should work. Good luck.
set theNumber to 3
set theFiles to {}
repeat
set file_path to (path to me) as text
set file_dir to file_path & ":sounds_dir:"
tell application "Finder" to set aFile to (some file of folder file_dir) as text
if aFile is not in theFiles then
set end of theFiles to aFile
tell application "Finder" to open file aFile
do shell script "afplay " & quoted form of POSIX path of aFile & " > /dev/null 2>&1 &"
end if
if (count of theFiles) is equal to theNumber then exit repeat
end repeat

AppleScript to read text file containing file names, search for each file name, and if a file is found copy it to a folder

Sorry to ask a question without even pasting my coding attempt, but I've never used AppleScript before and I have no idea how I would do this. I've found bits of code online that do small parts of each step of this, but some of the key parts I can't figure out how to do. If I can get this figured out it would save a lot of time. Basically my problem is that a client sent over thousands of photos, all in multiple levels of sub folders, along with an Excel document containing about 300 file names that I need to pull out and use. I can copy the file names from the Excel document into a plain text file, either multi-line or comma separated.
So this is what I need to do:
Open folder selector dialog to select the destination folder
Open file selector dialog to select the text file
Loop through each line (or comma separated value) of the text file
Take that string and search for a file name containing the string
Copy the first result into a folder (let's say Desktop:Found Photos)
If a file could not be found matching the string then add the search string into a text file (so I could email it to the client and ask them to send it to me)
If you can't code this whole process, if you could help me with looping through the text file, searching for the file name and copying the first result to another folder, and adding the file name to a text file if a file wasn't found, then I could probably piece it it all together. Thanks for any help.
You can try something along the lines of:
set newFolder to POSIX path of (path to desktop as text) & "Found Photos"
do shell script "mkdir -p " & quoted form of newFolder
set filePaths to paragraphs of (read (choose file with prompt "Select file list") as «class utf8»)
set fileFolder to POSIX path of (choose folder with prompt "Select folder containing files")
set foundFiles to {}
repeat with fileName in filePaths
set fileName to (contents of fileName)
set xxx to do shell script "find " & quoted form of fileFolder & " -name " & quoted form of fileName
if xxx ≠ "" then
tell application "System Events" to move file xxx to newFolder
set end of foundFiles to fileName & return
end if
end repeat
set foundFiles to (foundFiles as text)
do shell script "echo " & quoted form of foundFiles & " > " & quoted form of POSIX path of ((path to desktop as text) & "FoundFiles.txt")
It might have been easier to use shell scripting:
IFS=$'\n'
mkdir -p ~/Desktop/target/
for l in $(cat ~/Desktop/files.txt); do
found=$(find ~/Documents/source -type f -name "*$l*")
[[ -n $found ]] && cp $found ~/Desktop/target/ || echo "$l"
done

Moving files into folders / subfolders based on file names [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
Hope someone can help me,
To start out, my AppleScript skills are almost non-existing.
I get a number of files for archiving purposes in the following format which need sorting. The format is first the device name, followed by a run number and a sample number followed by some text.
Example file: "UZLA 55879 [05x13] september cal run.cdf" (file format varies)
Which needs to be moved into a folder: ~/UZLA 55879 (LCMS)/Run 5/
The device name is fairly random, sometimes just a number sometimes the entire official naming.
The main folder has a secondary item in brackets after the device name which is not in the file name that is being moved. the string before "[" and "(" do match, after the main name it's different.
The subfolder doesn't always exist, when a new run is started the folder /Run 6/ for example might not exist. Their's no 0 padding to the numbers
The files all arrive in the same folder and their should be no other files located in that folder.
To round this of we like to make an alias in a single folder on the main drive (files are moved to external system) for direct access, which is easy for quick last think look up but entirely unwieldy for the whole system (older aliases are deleted from it by other script).
Thanks.
Okay, so this was annoyingly closed, appearance because it only helps me and not random person from the future. Getting help for me was kinda the point. This is where we're at, with thanks to adayzdone:
set myFolder to (choose folder)
tell application "System Events" to set folderName to myFolder's name
set {TID, text item delimiters} to {text item delimiters, {"(", ")"}}
set myText to text item 2 of folderName
set text item delimiters to TID
set myFiles to every paragraph of (do shell script "find " & quoted form of (POSIX path of myFolder) & " \\! -name \".*\" -type f")
repeat with aFile in myFiles
set aFile to aFile as text
tell application "Finder" to set fileName to name of (POSIX file aFile as alias)
set newPath to "~/" & quoted form of (do shell script "echo " & quoted form of fileName & " | sed -e 's/\\[0/\\[/' -e 's/\\([^\\[]*\\)\\[\\([0-9]*\\)x[0-9]*\\].*/\\1(" & myText & ")\\/Run \\2\\//'") as text
do shell script "mkdir -p " & newPath & " ; mv " & quoted form of aFile & space & newPath
end repeat
This gives the following error: error "Can’t get text item 2 of \"testFolder\"." number -1728 from text item 2 of "testFolder"
Let me clarify: I have a bunch of files in a folder named /testFolder/ (always named that, all files enter here) what I want is to move the files into folders and subfolders in a given format based on the file names.
Example: File: /UZLA 55879 [01x05] XXX.cdf
Base name "UZLA 55879", the folder /UZLA 55879 (LCMS)/ exists at the destination. the (LCMS) is irrelevant to the move, it's just extra junk on the folder name, the script should detect that the folder exists (despite what junk comes between the ()" and use it as it's destination. If no folder with that base name exist it can just pop up an error or crash the whole script, that's not really the issue as new base names are rarely created and are named manually (and rather randomly) anyway.
The second part of the name is [01x05] the first part of that, "01" is detected (stripped from its padding zero) and moved into subfolder /Run 1/ (If it's "[05x07] is goes into /Run 7/ etc. the rest of the file name/extention is irrelevant to the move.
Current issue: The script now tries to pull the info from the starting folder to choose the destination folder, the starting folder is (not) named /UZLA 55879 (LCMS)/ it uses that "LCMS" to create the destination folder. (which it can't since the starting folder is 1) not named that and 2)) every destination folder has a different item (some are the same though) between those parentheses so naming the starting folder like that is useless. The script uses " & myText & " for that, that string has to be a random string which is defined by the destination folder not the starting folder.
I would normally not answer a question like this unless the user has put some effort into it, but I am a sucker for regular expressions.
set sourceFolder to "/Users/You/Desktop/testFolder"
set destFolder to "/Users/You/Desktop/testFolder2"
set myFiles to every paragraph of (do shell script "find " & quoted form of sourceFolder & " \\! -name \".*\" -type f")
repeat with aFile in myFiles
set aFile to aFile as text
tell application "Finder" to set fileName to name of (POSIX file aFile as alias)
-- Find name of parent folder
set parentName to do shell script "echo " & quoted form of fileName & " | sed 's/ \\[.*//'"
tell application "System Events" to set parentFolder to POSIX path of (first folder of folder destFolder whose name starts with parentName)
-- Extract the text between ( and )
set myText to do shell script "echo " & quoted form of parentFolder & " | sed 's/.*(\\(.*\\)).*/\\1/'"
set newPath to quoted form of (destFolder & "/" & (do shell script "echo " & quoted form of fileName & " | sed -e 's/\\[0/\\[/' -e 's/\\([^\\[]*\\)\\[\\([0-9]*\\)x[0-9]*\\].*/\\1(" & myText & ")\\/Run \\2\\//'") as text)
do shell script "mkdir -p " & newPath & " ; mv " & quoted form of aFile & space & newPath
end repeat

Use Automator/Applescript to crop filenames after certain character?

I have a folder containing about 5000 files with names like:
Invoice 10.1 (2012) (Digital) (4-Attachments).pdf
Carbon Copy - Invoice No 02 (2010) (2 Copies) (Filed).pdf
01.Reciept #04 (Scanned-Copy).doc
I want to rename these files by removing everything from the first bracket onwards, so they look like this:
Invoice 10.1.pdf
Carbon Copy - Invoice No 02.pdf
01.Reciept #04.doc
I have found lots of scripts that will remove the last x letters, but nothing that will crop from a particular character.
Ideally I would like to use Automator, but I'm guess this might too complex for it. Any ideas?
Try:
set xxx to (choose folder)
tell application "Finder"
set yyy to every paragraph of (do shell script "ls " & POSIX path of xxx)
repeat with i from 1 to count of yyy
set theName to item i of yyy
set name of (file theName of xxx) to (do shell script "echo " & quoted form of theName & " | sed s'/ (.*)//'")
end repeat
end tell
The code posted by #adayzone will work, but there is no need to use sed for this – plain AppleScript will do, using offset:
set fullString to "Invoice 10.1 (2012) (Digital) (4-Attachments).pdf"
set trimmedString to text 1 thru ((offset of "(" in fullString) - 1) of fullString
-- trim trailing spaces
repeat while trimmedString ends with " "
set trimmedString to text 1 thru -2 of trimmedString
end repeat
this returns “Invoice 10.1". To split the file name into the name and extension, and re-add the extension, you can use System Events’ Disk-File-Folder suite, which will provide the handy name extension property you can store and re-add after trimming the name.
Assuming you use some Automator action to get the files to be processed, the full processing workflow would be to add an AppleScript action after the file selection part with the following code:
repeat with theFile in (input as list)
tell application "System Events"
set theFileAsDiskItem to disk item ((theFile as alias) as text)
set theFileExtension to name extension of theFileAsDiskItem
set fullString to name of theFileAsDiskItem
-- <insert code shown above here>
set name of theFileAsDiskItem to trimmedString & "." & theFileExtension
end tell
end repeat
If you want your Automator workflow to process the files any further, you will also have to create a list of aliases to the renamed files and return that from the AppleScript action (instead of input, which, of course, is not valid anymore).

Getting the file name of files dropped on the script

I made this Applescript script to create symbolic links.
Appart from POSIX path of, how can I get the file name, without the path, of the dropped file?
on open filelist
repeat with i in filelist
do shell script "ln -s " & POSIX path of i & " /Users/me/Desktop/symlink"
end repeat
end open
PS: I know this expects many files to be dropped and tries to create many links with the same name, which gives an error. Actually I copied this example from a website and as I don't know almost anything about Applescript, I don't know how to do this for a single file, help on that would be appreciated too.
I'm not sure what precisely you're trying to do, but I have a guess. Is the idea that you want to take every file dropped on the script and create a symbolic link to each one on the Desktop? So if I drop ~/look/at/me and ~/an/example, you'll have ~/Desktop/me and ~/Desktop/example? If that's what you want, then you're in luck: ln -s <file1> <file2> ... <directory> does exactly that. (Edit: Although you have to watch out for the two-argument case.) Thus, your code could look like this:
-- EDITED: Added the conditional setting of `dest` to prevent errors in the
-- two-arguments-to-ln case (see my comment).
on quoted(f)
return quoted form of POSIX path of f
end quoted
on open filelist
if filelist is {} then return
set dest to missing value
if (count of filelist) is 1 then
tell application "System Events" to set n to the name of item 1 of filelist
set dest to (path to desktop as string) & n
else
set dest to path to desktop
end if
set cmd to "ln -s"
repeat with f in filelist & dest
set cmd to cmd & " " & quoted(f)
end repeat
do shell script cmd
end open
Note the use of quoted form of; it wraps its argument in single quotes so executing in in the shell won't do anything funny.
If you want to get at the name of the file for another reason, you don't need to call out to the Finder; you can use System Events instead:
tell application "System Events" to get name of myAlias
will return the name of the file stored in myAlias.
Edit: If you want to do something to a single file, it's pretty easy. Instead of using repeat to iterate over every file, just perform the same action on the first file, accessed by item 1 of theList. So in this case, you might want something like this:
-- EDITED: Fixed the "linking a directory" case (see my comment).
on quoted(f)
return quoted form of POSIX path of f
end quoted
on open filelist
if filelist is {} then return
set f to item 1 of filelist
tell application "System Events" to set n to the name of f
do shell script "ln -s " & ¬
quoted(f) & " " & quoted((path to desktop as string) & n)
end open
It's pretty much the same, but we grab the first item in filelist and ignore the rest. Additionally, at the end, we display a dialog containing the name of the symlink, so the user knows what just happened.
As an example, you can work with the Finder instead of a shell script to get the name of a single file that is dropped on the script that is saved as an application. If you don't need the display dialog, you can remove it, but you have the file name as a variable to work with:
on open the_files
repeat with i from 1 to the count of the_files
tell application "Finder"
set myFileName to name of (item i of the_files)
end tell
display dialog "The file's name is " & myFileName
end repeat
end open

Resources