I'm writing an AppleScript in which I want to insert a subroutine to delete specified files. With a flag I wish to control whether the given file is moved to the recycle bin or deleted permanently.
Actually my script looks like this:
on MyDeleteProc(theFile, allowUndo)
if allowUndo then
tell application "Finder" to delete POSIX file theFile
else
do shell script "rm " & theFile
end if
end MyDeleteProc
Now I want to know if this case is correct so far or is there maybe another Finder command or a parameter for the delete command that I overlooked so I will be able to simplify the script above?
AppleScript is a temperamental beast, and the devil is often in the details.
While #adayzdone's answer provides the crucial pointer - use of the System Events application's delete command to achieve permanent deletion, working out the exact syntax takes trial and error:
Caveat: This handler works with both files and folders - targeting a folder with allowUndo set to false therefore permanently deletes that folder's entire subtree.
on MyDeleteProc(theFile, allowUndo)
if allowUndo then
tell application "Finder" to delete theFile as POSIX file
else
tell application "System Events" to delete alias theFile
end if
end MyDeleteProc
On OS X 10.9.4 I had to do the following to make this work:
Finder context: Had to change POSIX file theFile to theFile as POSIX file (postfix form) - don't ask me why.
System Events context: Using "cast" alias with the POSIX path provided is the only form of the command that worked for me.
That said, a little tweak to your original function would make it work, too (and unless you delete many files one by one, performance probably won't matter):
Note, however, that just using rm only works with files - if you wanted to extend it to folders, too, use rm -rf instead - the same caveat re permanently deleting entire subtrees applies.
on MyDeleteProc(theFile, allowUndo)
if allowUndo then
tell application "Finder" to delete theFile as POSIX file
else
do shell script "rm " & quoted form of theFile
end if
end MyDeleteProc
Note the use of quoted form of, which safely passes the file path to the shell, encoding characters such as spaces properly.
You can use System Events to permanently delete a file.
Related
I'm getting the following error:
"The file isn’t compatible with QuickTime Player."
When using this script:
tell application "Finder"
set random_file to some file of entire contents of folder "Movies" of home
open result
end tell
However, I am able to open the file from the finder manually and once I do the script works on just that file. The problem is I have thousands of files and don't want to open each one manually for the script to work again. Have not had this problem with the script in the past.
There are two ways I can think of to approach modifying your script:
Stick with Finder's open command but invoke it fully with its using parameter, which accepts an application file that informs Finder of the application that will be used to open the file. It may sound superfluous given it already tries to open it in QuickTime, and we're not trying to change that, but it's not unwise to see if it does confer a difference in behaviour:
tell application id "com.apple.finder"
tell the folder (path to movies folder) to tell (the ¬
a reference to entire contents) to tell (the ¬
some document file as alias) to set f to it
open f using application file id "com.apple.QuickTimePlayerX"
end tell
Grab the file as you like (really, you ought to be using System Events for this, not Finder, but I'll go with what you had), but then use the open handler of the specific application to open the file:
tell application id "com.apple.finder" to tell the folder (path to movies folder) ¬
to tell (a reference to the entire contents) to tell (some document file) ¬
as alias to set f to it
tell application id "com.apple.QuickTimePlayerX"
activate
open f
end tell
NB. I'm using Monterey, in which both of these two above propositions work appropriately. This doesn't necessarily infer that it will do so in Big Sur, but if they do not, it's worth checking the various app permissions under the different Security & Privacy headings of System Preferences.
Using Shake, to create an mp3 (this is just a learning example), I use lame, and then id3v2 to tag it.
If the lame succeeds, but the id3v2 fails, then I'm left with the mp3 file in place; but of course it is "wrong". I was looking for an option to automatically delete target files if a producing command errors, but I can't find anything. I can do this manually by checking the exit code and using removeFiles, or by building in a temporary directory and moving as the last step; but this seems like a common-enough requirement (make does this by default), so I wonder if there's a function or simple technique that I'm just not seeing.
The reason Make does this by default is that if Make has a partial incomplete file on disk, it considers the task to have run successfully and be up to date, which breaks everything. In contrast, Shake records that a task ran successfully in a separate file (.shake.database), so it knows that your mp3 file isn't complete, and will rebuild it next time.
While Shake doesn't need you to delete the file, you might still want to so as to avoid confusing users. You can do that with actionOnException, something like:
let generateMp3 = do cmd "lame" ... ; cmd "id3v2" ...
let deleteMp3 = removeFile "foo.mp3"
actionOnException generateMp3 deleteMp3
Question:
Can inotify be used to reliably record files in a [linux] system?
Details:
I am attempting to use inotifywait to track users movements (currently using bash, but it has been suggested that I migrate to a scripting language). Ultimately I want to add new files to a database upon creation (create, moved_from), update existing rows in a database upon file modification (modify, attrib, move_to), and finally remove a row upon file deletion (delete). I am, however, running into many problems as even an action as seemingly simple as save, generates many inotifywait messages. Observe the following commands and their output (note, the use of /home/user/ is purely for example purposes):
Examples:
Example 1: Listen for file creation:
$ inotifywait -mr /home/user/ -e create --format %w:%f:%e:%T --timefmt %T
Touch:
$touch test.txt
/home/user/:test.txt:CREATE:21:35:30
Open a new file with vim then issue :w command:
$vim test2.txt
/home/user/:test2.txt:CREATE:21:35:30
Open an existing file with vim then issue :w command:
$vim test2.txt
/home/user/:4913:CREATE:21:35:30
/home/user/:test2.txt:CREATE:21:35:30
Open a new file with gedit then click save:
$gedit test3.txt
/home/user/:test3.txt~:CREATE:21:35:30
Open an existing file with gedit then click save:
$gedit test3.txt
/home/user/:.goutputstream-HN3ZDW:CREATE:21:35:30
/home/user/:test3.txt~:CREATE:21:35:30
Note that not only are two new files displayed as having ben created (4913 and .goutputstream-HN3ZDW), but also that the only file being created is test3.txt~ and not test3.txt, even though the file test3.txt is created when checked with the ls command. For completeness, here is the above example, but with a few more options.
Example 1: Listen for file creation, modification, deltion, and movement:
$ inotifywait -mr /home/user/ -e create -e modify -e delete -e moved_to -e moved_from --format %w:%f:%e:%T --timefmt %T
Touch:
$touch test.txt
/home/user/:test.txt:CREATE:21:35:30
Open a new file with vim then issue :w command:
$vim test2.txt
/home/user/:test2.txt:CREATE:22:12:32
Open an existing file with vim then issue :w command:
$vim test2.txt
/home/user/:4913:CREATE:22:04:35
/home/user/:4913:DELETE:22:04:35
/home/user/:test2.txt:MOVED_FROM:22:04:35
/home/user/:test2.txt~:MOVED_TO:22:04:35
/home/user/:test2.txt:CREATE:22:04:35
/home/user/:test2.txt~:DELETE:22:04:35
Open a new file with gedit then click save:
$gedit test3.txt
/home/user/:test3.txt~:CREATE:21:35:30
Open an existing file with gedit then click save:
$gedit test3.txt
/home/user/:.goutputstream-0WQ2DW:CREATE:22:06:34
/home/user/:test3.txt~:CREATE:22:06:34
/home/user/:.goutputstream-0WQ2DW:MOVED_FROM:22:06:34
/home/user/:test3.txt:MOVED_TO:22:06:34
Basically my question is "is it possible to use inotify to update a file in a database"? For example, if a user edits a file and saves it, I want it to be reflected in the database as an update to that file, and not a brand new file replacing a completely different file. Any help would be greatly appreciated, even if it's a suggestion pointing me in a different direction.
inotify tells you what happens like it happens.
Gedit, like most editors, saves by first writing a temporary file then moving that file into place. This avoids overwriting the file with a half-written version in case the editor or the whole system crashes while the file is being written. Vim takes a different approach (this can be configured, I won't go into details here — see e.g. why inode value changes when we edit in “vi” editor?): it first creates a temporary backup file, then writes the new file.
If you want these to be recorded as a single editing event, you'll have to perform some pattern recognition on the even log. A create-write-move sequence that replaces an existing file and a create-move-create delete sequence like vim's would be the archetypal patterns. Note that the pattern might be interleaved with other events.
I have a suspicion that there's a better way to do what you want to do, but I don't understand what you're trying to do. If you're trying to log user actions, you have already found a way, but there are simpler ways: loggedfs or the audit subsystem. If you want to keep a backup of all file versions, either hook up the editor to a version control system (this lets users control what gets backed up) or use a versioning filesystem such as copyfs. You can even store the files in the database directly, by using a filesystem like mysqlfs or postgresqlfs (admittedly neither project looks maintained).
I have a strange file in my file system without the extension part. The filename is "15.". The weird thing is that it is not one of those without the dot part (like just "15"), but the one with the dot but no extension ("15.") -- it is literally an illegal filename in windows, and not sure how did it get created in the first place.
I know it is a text file and it is about 15KB in size; however, due to the weirdness in name, I can't open it with any application -- I've tried to open in notepad, wordpad, etc., have tried the 'type' command to spit it out on commans shell, tried to shell-open enclosing filename in quotes, and so on -- all methods result in a 'file not found' error except the notepad, which says '15.txt' is not found.
Due to the nature of the issue and the way search engines optimize the search, it is extemely hard to search for an answer in any of the search engines online. So, I just wanted to put this question out there and see if anybody had to deal with a similar issue and have found any way to rename the file or even to change the extension.
Filenames that are valid in NTFS but cannot be used from Windows can be created when accesing disks or shares from other operating systems like Linux.
If you don't have a Linux installation at hand, then get hold of a "live" CD, boot Linux, and change the filename.
That may sound like a hassle, but Windows-only solutions (moving stuff around, deleting the directory) are even worse.
Use REN: http://ss64.com/nt/ren.html
It is a command prompt command (run > cmd > cd wherever > ren 15. 15.txt )
I'm trying to check if a file exists or not in Tcl, but I can't seem to get a true result. Even though I know it is present.
while {true} {
if { [file exists $file_name] == 1} {
exp_send "copy file.txt destination \r"
puts " File copied!"
}
puts "File Not copied"
}
I always execute the File not copied line. I did a put for [file exists $file_name] and I always end up with 0. But I know for a fact that the file exists in the current directory. Any suggestions?
EDIT:
An alternative method that I'm trying to pursue, is that when I do a dir using the tcl script. I will get an output of all the files in the directory. I just need to match my file with the list outputted and satisfy the if when a match was found ...
I'm executing the script from Location A, but using the script to telnet to Location B. When I do a file exists, it checks Location A itself. This is my problem ... since I need to be searching in Location B ...
The file exists command always works with local filesystems. If you want to check whether a remote system has a file, you'll have to exp_send it some instructions to do the check for you. Unfortunately, I can't quite tell what you're talking to from your description, so I can't actually advise how to do it.
And you want a break after that puts "File copied" line otherwise it will all go round the loop again. You probably don't want that!
Donal reasonably mentioned exp_send as a vehicle to access a remote filesystem. If this is an FTP context, though, I prefer a (pure-Tcl-without-Expect) solution based on Tcl's FTP library; I find this more portable, understandable, and concise.