What I'm trying to do is essentially shred a file. I was recently in a security protocol meeting at my company, and one of the speakers showed us how he could recover a file that was put in the trash folder and then emptied from the hard drive. Being a new guy on the IT team, they asked me if I could find a way to "shred" the file. Essentially what I want to do is this:
-drag/send a file to a folder/applet:
-have an AppleScript open the file in text edit:
-use a "randomly" generated ASCII string (see below) to encrypt/corrupt the text:
-save the file, and then delete it with the "remove" shell script:
-if at all possible, find a way to instantly rewrite the part of the drive that contained the file previously:
This is what I have so far. It's just pieced from previous projects I did and some looking online.
--this is the "random" generator
set passphrase to ""
repeat with x from 1 to 100
set randomChar to ASCII character (random number from 50 to 100)
set passphrase to passphrase & randomChar
end repeat
--end generator
tell application "Finder"
set sel to selection
if sel is not {} then
set als to sel's item 1 as alias
set aPath to POSIX path of als
set oldPath to aPath & ".old"
set oldPath2 to quoted form of oldPath
set aPath2 to quoted form of aPath
--display dialog "Enter a password for encryption" default answer "password"
set password1 to passphrase
set scRi to "openssl des3 -in " & oldPath2 & " -out " & aPath2 & " -k " & quoted form of password1
set RenameToOld to "mv " & aPath2 & " " & oldPath2
set DeleteOld to "srm " & oldPath2
--display dialog scRi
tell application "Terminal"
activate
do shell script (RenameToOld)
do shell script (scRi)
do shell script (DeleteOld)
end tell
end if
end tell
end open
sorry if the spacing is off. I keep getting an error saying that the variable "passphrase" is not defined, even though I tried to fix it plenty of times. It seems to corrupt any file it is handed, but I don't know why or how. If somebody could figure out how to get it to work, I would be very grateful.
The srm command is gone in 10.12, along with Finder's Secure Delete option. Apple sensibly eliminated them as they don't work on SSDs, nor do they destroy previously written or backup copies. As the new IT guy you really need to educate yourself before you take responsibility for anything security-related. See also: Security Theater.
Related
I am trying to write a simple logger with Applescript. I have a couple of questions
Firstly I am testing if a file exists, if it does not I want to create a file with that name and set the first line to a string "Counter:0".
So far I have this but my syntax is wrong. Appreciate any help as the info on the web is a bit slender.
tell application "Finder"
set thePath to "/Data/GameLog/"
set theFile to thePath & (do shell script "date '+%Y.%m.%d'" & ".log")
if exists POSIX file thePath then
--display dialog "Found"
else
do shell script "Counter:0" > echo thePath
end if
end tell
secondly I would like to read the first line of the file (ie Counter:0) and increment the integer after the : by 1.
Help v.much appreciated
Based on vadian's answer:
set logFolder to (POSIX path of (path to home folder)) & "Desktop/" -- the trailing slash is crucial
set timeStamp to do shell script "date '+%Y.%m.%d'"
set logFile to logFolder & timeStamp & ".log"
if ((do shell script "test -d " & quoted form of logFolder & "&& echo true||echo false") as boolean) then
try
close access logFile
end try
try
set fileReference to open for access logFile with write permission
on error
display alert "File already open"
return -1
end try
set counter to (get eof of fileReference)
if counter is not 0 then
try
set counter to (read fileReference from 9) as integer
on error
close access logFile
display alert "Read error"
return -1
end try
set counter to counter + 1
set eof of fileReference to 0
end if
write ("Counter:" & counter) to fileReference as «class utf8»
close access logFile
else
display alert "Folder does not exist"
end if
The advantage is that this will not ignore errors. It will also be able to find your home directory without needing you to manually enter it in code. This is safe since we check for the logFolder first. The rest of the code can't fail if that folder exists. I am aware that AppleScript has a method for checking whether or not a file exists, but I have found that functionality to be fairly difficult to use when dealing with POSIX paths, so I'm using a do shell script instead, which naturally deals with POSIX paths.
Please try this, change the file path in the first line (consider the trailing slash)
set logFolder to "/Users/myUser/Desktop/" -- the trailing slash is crucial
set timeStamp to do shell script "date '+%Y.%m.%d'"
set logFile to logFolder & timeStamp & ".log"
try
set fileReference to open for access logFile with write permission
set counter to (get eof of fileReference)
if counter is not 0 then
set counter to read fileReference from 9
set counter to counter + 1
set eof of fileReference to 0
end if
write ("Counter:" & counter) to fileReference as «class utf8»
close access fileReference
on error
try
close access logFile
end try
end try
I'm trying to get duplicate home folders (desktop, movies, music, home, etc..) to a shared server. I was finally able to get the drive mounted using a concatenation of string and variables. But now i'm getting an error on the duplication line. If I mount the drive manually, this code works, but doesn't seem to work when mounting the drive through applescript
--Assigns variable to username
tell application "System Events"
set user_name to name of current user
end tell
--Prompts for eraider as string
set returnedName to (display dialog "Enter Raider Name:" default answer "eRaider" buttons {"Continue"} default button 1 giving up after 5)
--Sets string as variable
set work_name to text returned of returnedName
--Sets department list
set deptList to {"dept1", "dept2", "dept3", "dept4"}
set dept_name to {choose from list deptList} as string
--Tells Finder to mount shared drive
tell application "Finder"
mount volume ("smb://vserver/athletics/"&dept_name&"/"&work_name)
end tell
--Sets sever as variable
set vserver to POSIX file ("/Volumes/" & work_name)
--Copies Documents to Server
set source to POSIX file ("/Users/" & user_name & "/Documents")
tell application "Finder"
duplicate source to vserver with replacing
end tell
I get this error
error "Finder got an error: AppleEvent handler failed." number -10000
On this line: duplicate source to vserver with replacing
You have a few strange things in your code. Most of them do not affect your error however they should be corrected. For example the "mount volume" command is not a Finder command, it's an applescript command and thus you should not tell the Finder to perform that command. Next, the "choose file" line... why do you have brackets around it? Plus other small things. So I cleaned up the code.
To get to your specific problem it could be 2 things. First, I use an if statement to ensure the disk is mounted before trying to duplicate the files. Second, the "POSIX File" command could also cause problems. It's an unusual command in that it doesn't always work the way you expect. Therefore in this code, to ensure we avoid any issues with that command, I coerce it to text and then in the duplicate command I put it in the proper format by using the word "folder" in front of it.
So I did not test this code but it should work. I hope it helps.
--Assigns variable to username
tell application "System Events" to set user_name to name of current user
--Prompts for eraider as string
set work_name to text returned of (display dialog "Enter Raider Name:" default answer "eRaider" buttons {"Continue"} default button 1 giving up after 5)
--Sets department list
set deptList to {"dept1", "dept2", "dept3", "dept4"}
set dept_name to item 1 of (choose from list deptList)
--mount shared drive
mount volume ("smb://vserver/athletics/" & dept_name & "/" & work_name)
if work_name is in (list disks) then
--Copies Documents to Server
set source to (POSIX file ("/Users/" & user_name & "/Documents")) as text
tell application "Finder" to duplicate folder source to disk work_name with replacing
else
display dialog "Disk " & work_name & " is not mounted"
end if
An even better way would be to use the "path to" command to establish the path to your documents folder. This way you don't need to use "POSIX File" or even know the user name because the "path to" command automatically works for the current user. Plus I would do a little more error checking on the mount volume stuff. So really this is how I would write your code... I didn't test this either!
--Prompts for eraider as string
set work_name to text returned of (display dialog "Enter Raider Name:" default answer "eRaider" buttons {"Continue"} default button 1 giving up after 5)
--Sets department list
set deptList to {"dept1", "dept2", "dept3", "dept4"}
set dept_name to item 1 of (choose from list deptList)
--mount shared drive
set isMounted to false
if work_name is not in (list disks) then
mount volume ("smb://vserver/athletics/" & dept_name & "/" & work_name)
-- wait for the volume to be mounted but only wait for a limited time before failing (10 seconds in this case)
set inTime to current date
repeat
delay 0.2
if work_name is in (list disks) then
set isMounted to true
exit repeat
end if
if (current date) - inTime is greater than 10 then exit repeat
end repeat
else
set isMounted to true
end if
--Copies Documents to Server
if isMounted then
set source to path to documents folder
tell application "Finder" to duplicate source to disk work_name with replacing
else
display dialog "There was an error mounting disk " & work_name buttons {"OK"} default button 1
end if
I want to make an automator app which creates an empty file in current directory.
I did some google search and found:
http://hints.macworld.com/article.php?story=20050219134457298 and http://hints.macworld.com/article.php?story=20100509134904820
However, I want to do something more powerful.
If the specified file already exists, I want to show a warning instead of overwriting the original file, which is what one of the above link does. (The other one creates a text file using textEdit. I do not want to create text file. I want an empty file like what linux/unix does)
I already figured out how to do most of the part, but
How can check whether a file exists in current directory using applescript??
How can I concatenate two variable in applescript?
Checking if a file exists (assuming thefullpath is already set as in the referenced question):
tell application "Finder"
if exists POSIX file thefullpath then
--do something here like
display alert "Warning: the file already exists"
end if
end tell
Not sure what you mean by the second part but if you want to concatenate strings stored in var1 and var2 you could simply do
var1 & var2
Something I have been using a lot of late for this sort of thing is the command /bin/test
The test test for the existence of in this case a file
if (do shell script "/bin/test -e " & quoted form of (POSIX path of theFile) & " ; echo $?") is "1" then
-- 1 is false
--do something
end if
The -e option:
-e file True if file exists (regardless of type).
The are tons of other test options shown in the /bin/test man page
The following code, adapted from your second link, is usually right, but it doesn't always work. The current directory is better specified as the directory of the document that is being opened which is most likely from the Finder's front window, but not necessarily. I like to write code that will work no matter what.
on run {input, parameters}
tell application "Finder"
set currentPath to insertion location as text
set x to POSIX path of currentPath
display dialog "currentPath: " & (x as text)
end tell
return x
end run
I wrote a whole "Run AppleScript" action to put things into context:
on run {input, parameters}
# count the number of files
set numFiles to 0
repeat with f in input
# warn the user that folders are not processed in this app
tell application "Finder"
if (kind of f is "Folder") then
display dialog "The item: " & (f as text) & " is a folder. Only files are allowed. Do you want to continue processing files or do you want to cancel?"
else
set numFiles to numFiles + 1
end if
end tell
end repeat
# require that at least one file is being opened
if numFiles < 1 then
display alert "Error: the application Test1.app cannot be run because it requires at least one file as input"
error number -128
end if
# get the current directory from the first file
set theFirstFile to (item 1 of input)
tell application "System Events" to set theFolder to (container of theFirstFile)
# ask the user for a file name
set thefilename to text returned of (display dialog "Create file named:" default answer "filename")
# create the file
tell application "System Events" to set thefullpath to (POSIX path of theFolder) & "/" & thefilename
set theCommand to "touch \"" & thefullpath & "\""
do shell script theCommand
# return the input as the output
return input
end run
The "touch" command is OK. If the file doesn't exist, it is created and if it does exist, only the modification date is changed (which isn't too bad) but it doesn't overwrite the file. If your file is being overwritten, it's not the touch command that is doing it.
I changed the default file name to remove the extension ".txt" This extension may default to being opened by TextEdit.app, but you can change this in the Finder by choosing "Get Info" for a file and changing the "Open With" property. You can change which application opens the file with that extension or you can change them all. For example, all of my ".txt" files are opened with BBEdit.app
Will you vote my answer up?
Another option that doesn't require Finder or System Events is to try to coerce a POSIX file or file object to an alias:
try
POSIX file "/tmp/test" as alias
true
on error
false
end try
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).
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