File finder script for networked files

Ive tried to do this script and failed. Hopefully someone can help me.

I need to:

  1. do a search across 6 networked computers to find a file.(Needs to ask for a file name)
  2. If the computers arent mounted the need to be mounted
  3. Once that file is found i need a window showing what the computer name and folder it is located on, and all the info of the file itself.

any ideas?

Hi,

Firstly, this will mount your volumes if they are not already mounted:

try
	mount volume "smb://username:password@Volume_1"
	mount volume "smb://username:password@Volume_2"
	mount volume "smb://username:password@Volume_3"
	mount volume "smb://username:password@Volume_4"
	mount volume "smb://username:password@Volume_5"
	mount volume "smb://username:password@Volume_6"
end try

Obviously change the username, password and Volume address/name for each mount.

This will capture a search term:

set searchTerm to text returned of (display dialog "Enter search term" default answer "")

And this will search all mounted Volumes for the search term

set theSearch to do shell script "find -f /Volumes/ | grep " & quoted form of searchTerm

So all together that is;-

try
	mount volume "smb://username:password@Volume_1"
	mount volume "smb://username:password@Volume_2"
	mount volume "smb://username:password@Volume_3"
	mount volume "smb://username:password@Volume_4"
	mount volume "smb://username:password@Volume_5"
	mount volume "smb://username:password@Volume_6"
end try

set searchTerm to text returned of (display dialog "Enter search term" default answer "")

set theSearch to do shell script "find -f /Volumes/ | grep " & quoted form of searchTerm

WARNING
The last part (find) will probably take ‘forever!!’ especially as you are searching across 6 volumes. I would unmount any Volumes/discs that are not needed first. It could still take several hours (even days!!) to complete.

If you do run this and experience Script Editor becoming unresponsive (that is because it is running the find command), open Activity Monitor, look for the ‘find’ process name, then click the Quit Process button.

I really can’t think of a more efficient way to search every mounted volume. Anyone else know of a quicker method?

I’ve just had a thought!

If all of the networked computers are Macs, and they all have spotlight indexing on, mdfind may be the answer!

Change the last line of the above script to:

set theSearch to paragraphs of (do shell script "mdfind -interpret " & quoted form of searchTerm & " | grep Volumes")

Much quicker!

There are some problems with network volumes with spotlight enabled.

First of all spotlight isn’t enabled on samba volumes by default, only AFP volumes. Then you need to index every time a volume over and over again when it is mounted. So spotlight would be slower than a simple find command. Spotlight on network volumes has been very buggy in the past (don’t know for Lion).

Hmmm…

Would mount volume “afp://username:password@Volume_1” etc, be any better then?

The “find” command really will take AGES across 6 mounted Volumes! (Not to mention your own HD, which will be listed in the /Volumes/ directory.)

One way I have done something similar is to save a text file locally of a ‘find’ command, then ‘grep’ out whatever you are searching for.

do shell script "find /Volumes/ -name \\*.eps >~/EPS_Images.txt"

Gets all .eps files listed in a txt file.

Then

set theSearch to paragraphs of (do shell script "grep -e " & quoted form of searchTerm & " <~/EPS_Images.txt")

But even this is time consuming. The initial compiling of the list will still take a l–o–n–g time, so much so that I don’t think this would be a useable solution. :frowning:

Yes but in Leopard and early snow leopard there were some problems with updating the database.

AGES, maybe it takes a bit longer but find is fast for a file hierarchy scanner and spotlight is slow for a database, locate is faster but needs a manual update. What does /Volumes has to do with find? Find is smart enough not to go up in the parent chain again which means it doesn’t scan itself twice. WIth find you can also tell it has to look into certain directories

If performance is an issue then your code isn’t really optimized, why using a single process and not 6 sub processes with named pipes? If every volume has the same size you can still look into all volumes in just a few seconds.

A working solution is always better than a non-working or unreliable solution. I’ve mounted 5 afp volumes to my mac and start searching right away, you’ll see that spotlight will find nothing in the first place, when you tell spotlight to search the network volume it takes even longer to find those files. Spotlight showed me that indexing those volumes would take up more than 4 hours.

I’m not saying that one method is superior to the other but both have their flaws and as far as I know with network volumes spotlight isn’t watertight (yet).

Hi Mr. Wazzie,

My thinking behind specifying /Volumes was that I just wanted to search the mounted volumes and not the startup HD. I now realise that the startup HD is also listed in /Volumes so does indeed make this pointless. - Doh!

However if we list all Volumes with ls -n then grep out any local disks (based on permissions? - Does this work??), this should just return all ‘external’ volumes. We can then repeat the find on each of these one at a time.

I have also returned the start up volume in order to skip this in the repeat.

This is what I have come up with so far:

try
	mount volume "smb://username:password@Volume_1"
	mount volume "smb://username:password@Volume_2"
	mount volume "smb://username:password@Volume_3"
	mount volume "smb://username:password@Volume_4"
	mount volume "smb://username:password@Volume_5"
	mount volume "smb://username:password@Volume_6"
end try

set searchTerm to text returned of (display dialog "Enter search term" default answer "")

set mountedVols to paragraphs of (do shell script "ls -n /Volumes/ | grep -v xr-xr | awk {'print $9'}")
tell application "Finder" to set StartUpVol to the name of disk 1
set theSearch to {""}

repeat with i from 1 to number of items in mountedVols
	set thisVol to item i of mountedVols
	if thisVol ≠ "" and thisVol ≠ StartUpVol then
		set theSearch to theSearch & paragraphs of (do shell script "find -f /Volumes/" & thisVol & " | grep " & quoted form of searchTerm)
	end if
end repeat

I also realise why my ‘find’ was taking a long time - the volume I am searching is an 8Tb Volume with almost 7Tb of files on it. - This is slow even as a command typed in the Terminal.

The above does work on my system with volumes I mount. I guess we need to hear from the OP - G Postal.

Thank you for your help, Just one thing, this script will be used on other computers as well.

The search works, however when it comes to a drive that is local(mine is lead) it comes up with this message:

Connection Failed
The server “Lead” is available on your computer.
Access the volumes and files locally.

When i click ok it brings up the enter search term window without mounting the drives located after my drive. Is there a way to have this script ignore the local drives? I need to be able to use this script on all the computers in the group so i cant write it just for mine, otherwise i would just delete mounting my drive.

Here is the code


try
mount volume "afp://Copper._afpovertcp._tcp.local"
mount volume "afp://Zinc._afpovertcp._tcp.local"
mount volume "afp://Titanium._afpovertcp._tcp.local"
mount volume "afp://Lead._afpovertcp._tcp.local"
mount volume "afp://Thorium._afpovertcp._tcp.local"
mount volume "afp://Lithium._afpovertcp._tcp.local"

end try

set searchTerm to text returned of (display dialog "Enter search term" default answer "")

set theSearch to do shell script "find -f /Volumes/ | grep " & quoted form of searchTerm

if theSearch ≠ "" then
display alert "Files Found" message theSearch

end if
if theSearch = "" then
display alert "Files Not Found" message theSearch

end if

Ive just pieced parts together and come up up with it.

Thanks again everyone for your help!

Replace the first ‘try’ block with the following:

set localName to do shell script "systemsetup -getlocalsubnetname | cut -d' ' -f4"


set volsToMount to {"afp://Copper._afpovertcp._tcp.local", "afp://Zinc._afpovertcp._tcp.local", "afp://Titanium._afpovertcp._tcp.local", "afp://Lead._afpovertcp._tcp.local", "afp://Thorium._afpovertcp._tcp.local", "afp://Lithium._afpovertcp._tcp.local"}

repeat with i from 1 to number of items in volsToMount
	set thisVol to item i of volsToMount
	if thisVol does not contain localName then
		try
			mount volume thisVol
		end try
	end if
end repeat

This will get the name of the local volume, then mount every volume in the ‘volsToMount’ variable that does not contain the startup volume name.

This should work in theory, although I haven’t tested it!