Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove file if it exists

Tags:

haskell

What is the right way of doing this in Haskell?

if exists "foo.txt" then delete "foo.txt" doSomethingElse 

So far I have:

import System.Directory main = do         filename <- getFileNameSomehow         fileExists <- doesFileExist filename         if fileExists               then removeFile filename              ???         doSomethingElse 
like image 596
yogsototh Avatar asked Dec 14 '11 09:12

yogsototh


People also ask

How do you remove a file only if it exists?

Well, it's entirely impossible to remove a file that doesn't exist, so it seems that the concept of "delete a file only if it exists" is redundant. So, rm -f filename , or rm filename 2>> /dev/null , or [[ -r filename ]] && rm filename would be some options..

How do you remove a file if it exists Bash?

You can apply the 'rm' command to remove an existing file. In the following script, an empty file is created by using the 'touch' command to test 'rm' command. Next, 'rm' command is used to remove the file, test.

How do you delete a file in Python if it exists?

To delete a file if exists in Python, use the os. path. exists() and os. remove() method.


1 Answers

You would be better off removing the file and simply recovering if it does not exist:

import Prelude hiding (catch) import System.Directory import Control.Exception import System.IO.Error hiding (catch)  removeIfExists :: FilePath -> IO () removeIfExists fileName = removeFile fileName `catch` handleExists   where handleExists e           | isDoesNotExistError e = return ()           | otherwise = throwIO e 

This avoids the race condition of someone deleting the file between your code checking whether it exists and deletes it. It might not matter in your case, but it's good practice anyway.

Note the import Prelude hiding (catch) line — this is because the Prelude contains older functions from exception handling which are now deprecated in favour of Control.Exception, which also has a function named catch; the import line simply hides the Prelude's catch in favour of Control.Exception's.

However, that still leaves your more fundamental underlying question: how do you write conditionals in IO?

Well, in this case, it would suffice to simply do

when fileExists $ removeFile filename 

(using Control.Monad.when). But it's helpful here, as it usually is in Haskell, to look at the types.

Both branches of a conditional must have the same type. So to fill in

if fileExists     then removeFile filename     else ??? 

we should look at the type of removeFile filename; whatever ??? is, it has to have the same type.

System.Directory.removeFile has the type FilePath -> IO (), so removeFile filename has the type IO (). So what we want is an IO action with a result of type () that does nothing.

Well, the purpose of return is to construct an action that has no effects, and just returns a constant value, and return () has the right type for this: IO () (or more generally, (Monad m) => m ()). So ??? is return () (which you can see I used in my improved snippet above, to do nothing when removeFile fails because the file doesn't exist).

(By the way, you should now be able to implement when with the help of return (); it's really simple :))

Don't worry if you find it hard to get into the Haskell way of things at first — it'll come naturally in time, and when it does, it's very rewarding. :)

like image 128
ehird Avatar answered Sep 18 '22 13:09

ehird