How can I find files by content in Mac OS X? - macos

I want to find files at a given location whose content matches a given string. For example, there are a lot of files inside the desktop folder (or anywhere), like *.pdf, *.rtf, *.doc, *.txt, *.html and so on.
The user will be prompted to enter a string thistext and select the location /Users/UserName/Desktop. I want to get a list of the files from this location whose content contains thistext.
I found a command utility mdfind, but it returns the files whose name contains thistext as well. I don't want these files in the result list; I only want files whose content is thistext. I've used grep, but it's not working properly for me. Is there a way to customize grep or mdfind command to work for me?
Or if there is any AppleScript script available for performing such task?

I think there are some syntax errors in the above answer.
I just tested this in AppleScript, and it works for me in Yosemite 10.10.5:
set textToSearchFor to "YourTextHere"
set searchDir to "~/Documents/Test/"
set cmdStr to "mdfind 'kMDItemTextContent == \"*" & textToSearchFor & "*\"cd' -onlyin " & searchDir
set lstFiles to (do shell script cmdStr)
log lstFiles
Result:
(*/Users/UserName/Documents/Test/PDF_Log.txt*)

You can specify a query that only examines each file's text content, like so:
mdfind -onlyin ~/Desktop 'kMDItemTextContent == *thistext* cdw'
The cdw at the end of the query string means the comparison should ignore case, diacritics, and width (which is mostly relevant for text with Asian characters).
Also, if you're doing this from an app, you shouldn't invoke the mdfind command as a subprocess. You should use the NSMetadataQuery class to do it within your app.

Related

Mac Automator - Compress (ZIP) a folder and rename as original folder name without the entirety of the path

Hi all, total newbie to any kind of programming, but I've written an Automator workflow to do a repetitive task I do daily. Basically I'm prepping artwork files and folders to send out to printers.
The steps are as follows:
Set Value of Variable (variable is ArtworkFolder)
where I drop the artwork folder containing the illustrator file and
PDF
Get Specified Finder Items
locates a file on a RAID server
Copy Finder Items (to ArtworkFolder)
copies said file into the folder
Ask for Confirmation -
prompts user to select an updated PDF
Ask for Finder Items -
opens the folder where the new PDF sits
Copy Finder Items (to ArtworkFolder)-
copies PDF file into the folder (overwriting older files)
Ask for Confirmation
prompts user to select print guidelines
Ask for Finder Items
opens the folder where the print guidelines sit
Copy Finder Items (to variable ArtworkFolder) -
copies print guidelines into the folder
THIS IS WHERE I THINK IT MAY BE GOING AWRY
Get Value of Variable (ArtworkFolder)
this is supposed to get the name of the original folder
Get Specified Finder Items
and all its contents
Create Archive
Then Zip the whole lot together
But it zips it with the name Archive.zip which I don't want so...
Rename Finder Items: Replace Text
which is set to find "Archive" in basename only ignoring Case. then
replace that with the variable ArtworkFolder
but it renames the folder with the entire path
I've tried to strip out the path by adding…
Rename Finder Items: Replace Text
which is set to find everything in the path basename only up to the
unique folder name and replace with nothing (eg I left the Replace box
blank)
But then it duplicates the folder name like this:
00000- Test Artwork Folder/00000- Test Artwork Folder.zip
All I want is to original folder name (00000- Test Artwork Folder) as
the zip file name.
Any tips would be greatly received!
For whatever reason, Automator doesn't have an included action to get file names, so you will need to use a third-party action or do it yourself. A Run AppleScript action can be used, but either way, note that you will need to save the workflow items and use the Ignore Input option as appropriate around getting the names, so you don't get them mixed in with the file items (also note that the workflow and action items are a list).
To get the name of a single item, something like the following can be inserted into your workflow, where the variable for the name can be used in the rename action:
Set Value of Variable { Variable: Original Input } -- stash current items
Run AppleScript: -- get the name
on run {input, parameters}
set {theContainer, theName, theExtension} to getNamePieces from (first item of input)
return theName
end run
to getNamePieces from somePath
tell application "System Events" to tell disk item (somePath as text)
set _container to path of container
set {_name, _extension} to {name, name extension}
end tell
if _extension is not "" then
set _name to text 1 thru -((count _extension) + 2) of _name -- just the name part
set _extension to "." & _extension
end if
return {_container, _name, _extension}
end getNamePieces
Set Value of Variable { Variable: Item Name }
Get Value of Variable { Variable: Original Input } (Ignore Input) -- continue workflow

Windows 10 Command Prompt rename files overwrites file names instead of prepending

I have these files in a folder:
aaa.txt
bbb.txt
ccc.txt
I want to prepend all the filenames with 1_, so I try to write this in a Windows command prompt:
rename * 1_*
Doing so I want to get this result:
1_aaa.txt
1_bbb.txt
1_ccc.txt
But instead i get this:
1_a.txt
1_b.txt
1_c.txt
Instead of prepending it is just overwriting the names from the start. According to this (https://www.computerhope.com/renamehl.htm) article that is indeed the intended behavior.
But in this (https://www.windowscentral.com/how-rename-multiple-files-bulk-windows-10) article they show an example where they are increasing the length of the first part of the filename like this:
ren nyc_*.* newYork_*.*
So that seems to be similar to what I want to do, but when I try that exact example it does not work like that. Again, it just overwrites the first part the name without adding anything, and then I end up with nyc_(1).jpg becoming newYork_.jpg (the unique number is overwritten).
Is the second article plain wrong? How do I simply prepend something to a bunch of files with a batch line?
One method is to knock up a temporary batch file to do your renaming.
First, dump your directory to a text file with formatting turned off:
dir *.txt /B > list.bat
Open it in Notepad and then copy that bare listing into the likes of Excel (or if you have a text editor with powerful features you can use it.) You can then create a formula, like:
="rename " & A1 & " 1_" & A1
Which will build you a list of individual rename commands changing each file one at a time, like this:
A B
aaa.txt rename aaa.txt 1_aaa.txt
bbb.txt rename bbb.txt 1_bbb.txt
ccc.txt rename ccc.txt 1_ccc.txt
Copy that new column back into notepad and save it.
Run and discard your new batchfile and everything will be renamed over.
For your nyc to NewYork, you need a bit more work...
="rename " & A1 & " NewYork" & MID(A1,4,99)
...will strip the left three characters from the name replace them to give you:
rename nyc_(1).jpg NewYork_(1).jpg
forfiles /m *.txt /C "cmd /c rename #file 1_#file"

what is the correct path to the iMovie Projects folder to use in an AppleScript

I'm working on a simple AppleScript to make a copy of an iMovie project file. I have added this property to the script:
property iMovieProjects : alias (home directory of (system info) as string) & "Movies:iMovie Projects"
This gives me the error
File alias Macintosh HD:Users:my user name:Movies:iMovie Projects of wasn't found
What's the correct path? I tried iMovie Project.localized but that doesn't work either.
Try this, looks like you need to use the Finder. Also i added a little simplification on getting the home path.
property iMovieProjects : ""
tell application "Finder" to set iMovieProjects to alias ((home as string) & "Movies:iMovie Projects")
EDIT: Heres a one line solution that does not use the Finder, based on ideas from mklement0 & regulus6633
property iMovieProjects : alias ((path to movies folder as text) & "iMovie Projects.localized")
It appears this folder is some kind of special bundle type folder and thats why we were needing the finder to parse it correctly. Using its full .localized name resolves it.
UPDATE: As adamh discovered, the reason for the alias error is because the real name of the folder is "iMovie Projects.localized". Get info on the folder and you will see it.
I would add that an easier method to get to a folder is using the "path to" command. Using that you can get to virtually every known folder. In your case we can get directly to the Movies folder. You can look in the applescript dictionary of the standard additions to see all of the folders it knows. As such I would reference that folder as follows.
set iMovieProjects to alias ((path to movies folder as text) & "iMovie Projects.localized:")
Finally you'll notice that I did not use a property for iMovieProjects. That's because when you compile a script a property will hard-code the path into the script... meaning that the script will only work for this particular user. If the script is used by another user it will still point to the Movies folder of the person at compile time. Thus we don't use a property and the script will work for any user.
Good luck.
Update2 (thanks, #adamh): Even though the iMovie projects folder name appears as "iMovie Projects" in Finder in English-language locales, the actual - locale-independent - name is "iMovie Projects.localized". (If you want to refer to the folder by its localized name, prefix the set command with tell application "Finder", as in #adamh's answer's first snippet.)
You simply need to change how you parenthesize - the string to pass to alias must be built in its entirety inside parentheses:
property iMovieProjects : ""
set iMovieProjects to alias ( ¬
(home directory of (system info) as string) & "Movies:iMovie Projects.localized" ¬
)
Update1: #regulus6633 makes the excellent point that you shouldn't initialize a property with a specific user's path, as it will get compiled into the script. Thus, the above snippet initializes the property to an empty string and then assigns a value dynamically - which will then reflect the current user's path - in a separate set ... to statement.
Your original statement inadvertently creates a list with 2 elements, whose first element is a an alias of your home directory and whose second element is the string "Movies:iMovie Projects".
Simplified version with the path to command demonstrated in #regulus6633's answer (the same need to parenthesize applies):
property iMovieProjects : ""
set iMovieProjects to alias ( ¬
(path to movies folder as text) & "iMovie Projects.localized" ¬
)

can't locate my file in subfolder nor read it (applescript)

I want to read text in a list from a textfile "test.txt" that's located in a subfolder called "data". The text is formatted as plain text, every line ends with enter. After all I want to work around that my code could not be saved anymore because I stored too many data like set names to {"Adam", "Adele",... which pumped the sctp over 500kb, by reading huge lists from textfiles.
Which way I try, I end up getting the xyz.app-name in my set folder, I don't know how its better to use read or do it with POSIX, or I get permission trouble when I use container of to filter my filename, nor where to nest the code to open the file.
Can someone help me start?
EDIT
I tried a bit and got a solution that worked for me, reading my text in a list. See below.
Then I came to another problem: One list I could not save in MacOSRoman, so I had to use Unicode UTF-16. But I can't break myfile2 into a list anymore. Can someone help me out with this?
As a new user I could not upload my screenshot, so here is the code:
set List1 to (read file myFile1 using delimiters linefeed) as list
set List2 to (read file myFile2 using delimiters linefeed as Unicode text) as list
Try any of these:
set aData to read file "Mac OS X:Users:j0k:Desktop:text file.txt"
set bData to read POSIX file "/Users/j0k/Desktop/text file.txt"
set cData to read alias "Mac OS X:Users:j0k:Desktop:text file.txt"
set dData to do shell script "cat '/Users/j0k/Desktop/text file.txt'"
An easy way of getting the path to your file is to drag the file into the script editor.
EDIT:
tell application "Finder" to set myFolder to container of (path to me) as text
set myFile to myFolder & "Data:test.txt"
set aData to read file myFile

list subfolders using applescript

This is my first applescript. I thought I'd do something simple like navigating to a folder using a path and listing the subfolders...Unfortunately, I can't figure it out :-)
Here is what I've tried so far:
The first try:
tell application "Finder"
set the_folder to POSIX path of "Users:MyName:Doc"
log the_folder
set folder_list to every item of folder the_folder
log folder_list
end tell
This produces an error:
"Finder got an error: Can't get folder "/Users/MyName/Doc".
Could someone please:
1. Explain to me what I'm doing wrong.
2. Provide an example that works.
Thanks in advance.
btw the folder does exist on my machine...
UPDATE: Oops! It appears that I have given you the wrong information so I will give you the correct information.
The command POSIX path of requires a complete alias reference. By that I mean supplying the full file reference (i.e. <your_disk_name>:Users:<your_user_name>:somefolder:). Make sure that if you're referring to a folder that you end the reference with a colon (i.e. Macintosh HD:Users:). An improved version would look like this:
tell application "Finder"
set the_folder to (POSIX path of ("<your_disk_name>:Users:<your_user_name>:Doc:") as alias) as alias
set folder_list to every item of the_folder
end tell
OPTIONAL
To coerce a POSIX path (i.e. /Users/<your_user_name>/somefolder) back into an alias, two conversions are needed.
Conversion 1: The first step is to convert the reference into a file reference. To do this, place the words as POSIX file after the reference, like so:
"/Users/<your_user_name>/somefolder" as POSIX file
This code procudes a file reference in this form: file "<your_disk_name>:Users:<your_user_name>:somefolder:"
Conversion 2: Add a second coercion, as alias, to the end of the reference...
"/Users/<your_user_name>/somefolder" as POSIX file as alias
This code produces an actual alias reference: alias "<your_disk_name>:Users:<your_user_name>:somefolder:
If you have any questions, just ask. :)
Posix paths are paths you use at the command line and are "/" delimited. Applescript paths are ":" separated so just use those. Try this script to see what the path should look like...
set folderPath to (choose folder) as text

Resources