Giter Site home page Giter Site logo

haskell / directory Goto Github PK

View Code? Open in Web Editor NEW
57.0 22.0 47.0 2.75 MB

Platform-independent library for basic file system operations

Home Page: https://hackage.haskell.org/package/directory

License: Other

Haskell 96.23% C++ 0.13% M4 0.56% C 0.40% Shell 1.01% Python 1.67%

directory's Introduction

directory

Hackage Build status Dependencies status

Documentation can be found on Hackage. Changes between versions are recorded in the change log.

Building from Git repository

When building this package directly from the Git repository, one must run autoreconf -fi to generate the configure script needed by cabal configure. This requires Autoconf to be installed.

autoreconf -fi
cabal install

There is no need to run the configure script manually however, as cabal configure does that automatically.

directory's People

Contributors

argiopetech avatar ashleyyakeley avatar batterseapower avatar bgamari avatar bodigrim avatar dcoutts avatar donsbot avatar fuuzetsu avatar ggreif avatar guibou avatar hasufell avatar hvr avatar igfoo avatar jgoerzen avatar johnmeacham avatar josefs avatar lemmih avatar mchakravarty avatar mistuke avatar pcapriotti avatar pepeiborra avatar peti avatar redneb avatar rufflewind avatar ryanglscott avatar samb avatar simonmar avatar sjakobi avatar snoyberg avatar wz1000 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

directory's Issues

Creating a non-existent directory in the root directory silently fails

» git rev-parse HEAD
2cb6678
» cabal repl
Preprocessing library directory-1.2.1.1...
[1 of 1] Compiling System.Directory ( System/Directory.hs, dist/build/System/Directory.o )
[...]
*System.Directory> createDirectoryIfMissing True "/foo"
*System.Directory> createDirectoryIfMissing True "/foo/bar"
*** Exception: /foo/bar: createDirectory: does not exist (No such file or directory)

AFAICT

) `E.catch` ((\_ -> return ()) :: IOException -> IO ())
is swallowing the exception thrown by
else throw e
.

removeDirectoryRecursive can throw an exception if a file vanishes before it removes it

> removeDirectoryRecursive "/tmp/d"
Exception: /tmp/d/zzzzz: removeDirectoryRecursive: does not exist (No such file or directory)

Here /tmp/d/ contained a directory foo (with many subdirectories so it took some time to delete), and a subsequent file zzzzzz. Immediately after pressing enter in ghci, I launched a rm zzzzzz. So getDirectoryContents included the file, but it was gone by the time removeFile ran.

I feel that this is a surprising failure mode, and one that would be very easy to recover from, making uses of removeDirectoryRecursive more robust. If removeFile throws an exception due to the file no longer existing, removeDirectoryRecursive could continue with removing the rest of the directory and not propagate the exception.

(Testing rm -rf (on linux) in similar circumstances, I found that it skips over files that have already been deleted by something else, rather than failing.)

System.Directory does not infer Safe on old GHC

It appears that directory no longer asserts that it is TRUSTWORTHY as of version 1.2.3.0. This is fine for GHC 7.10 where the module infers that it is Safe. Unfortunately this is not the case on older version of GHC. A TRUSTWORTHY pragma is still necessary for these older version.

Using GHC 7.8.4:

System/Directory.hs:117:1:
    Foreign: Can't be safely imported! The module itself isn't safe.

remove cbits/directory.c file

or more generally rethink how to handle the cbits in future, they seem kinda redundant by now

this includes figuring out if there's anyone depending on the .h files that may break...

canonicalizePath does not fully canonicalize paths that contain dangling links

If you create a link brokenlink that points to a nonexistent file and then run canonicalizePath on brokenlink, you still get brokenlink back because the link is dangling. I think it makes more sense to return nonexistent instead.

Fixing this however, is quite tricky. The reason is that we can't trust realpath will work correctly on a nonexistent path: on Macs realpath has strange behavior with nonexistent paths (#23), and on Windows the “realpath”-equivalent (GetFinalPathName) requires an existing file to even work.

So this means our only option is to implement it using a readlink (or equivalent). But it may take more than one readlink calls to make this work, if there are more symbolic link components in the new path, Worse potentially this might loop, so we'd need a cutoff too.

All in all, this is (IMO) a fairly minor thing, but requires a lot of effort and testing to get right.

`canonicalizePath` throws error on non-existing path

I came across this in idris-lang/Idris-dev#2982. Steps to reproduce (running Ubuntu 14.04)

λ ~/Projects/ stack ghci --package directory
Run from outside a project, using implicit global project config
Using resolver: lts-5.1 from implicit global project's config file: /home/matt/.stack/global-project/stack.yaml
Configuring GHCi with the following packages: 
GHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help
Ok, modules loaded: none.
Prelude> import System.Directory
Prelude System.Directory> canonicalizePath "."
"/home/matt/Projects"
Prelude System.Directory> canonicalizePath "./asdf"
*** Exception: ./asdf: canonicalizePath: does not exist (No such file or directory)

The documentation says:

The input path does not have to point to an existing file or directory.

and it does seem like there's some error checking on that.

inconsistent behavior of removeDirectoryRecursive with symbolic links

The way removeDirectoryRecursive dir works right now is totally inconsistent:

  • If there's a directory-like symbolic link, the function removes it without recursing into it, unless the symbolic link is not removable for some reason (e.g. no permission), in which case it recurses into it and wipes out everything inside.
  • If dir itself is actually a directory-like symbolic link, it will recurse into it but fail to remove dir itself.

The causes of these two problems are:

  • Instead of explicitly checking whether path refers to a true directory, it assumes any unremovable file that also satisfies directoryExists must necessarily be a directory. This is false, because directoryExists dereferences the symbolic link.
  • getDirectoryContents should not be called until dir is verified to be a true directory.

Note that there are two possible ways to handle the case where dir is not a true directory:

  • One can delete it silently, similar to the behavior of the POSIX command rm -r.
  • Or one can raise an error, similar to the behavior of the Python function shutil.rmtree.

See also:

System.Directory.getPermissions does not work well on Windows 7

It works well for following code

System.Directory.getPermissions "/path/to/somewhere"

However getting error with this:

System.Directory.getPermissions "/path/to/somewhere/"
*** Exception: getPermissions: does not exist (No such file or directory)

The only difference is the path name. It gets error when having extra trailing slash.
It looks wired.

Thanks your help.

PS: Previous discussion at https://ghc.haskell.org/trac/ghc/ticket/8342

copyFile does not copy metadata

In https://ghc.haskell.org/trac/ghc/ticket/5251, GHC trac user Orphi reports:

The copyFile function fails to copy various metadata to do with a file.

(GHC 7.0.2, directory 1.1.0.0 - not that I expect it to matter.)

The cause is simple: Rather than calling an OS-specific "please copy this file" function, the directory package attempts to implement this logic itself. And does it completely wrong.

The fix should be easy; we just need somebody to figure out what the appropriate native OS function is on each platform.

copyFileWithMetadata doesn't preserve timestamps on Windows

I'd be interested in a copyFile operation that preserves timestamps. Any reason for copyFileWithMetadata behaviour to be different across platforms regarding timestamps?

Any of these seems fine:

  • remove the timestamps copy under Posix for copyFileWithTimestamps and add a new copyFileWithTimestamps
  • make copyFileWithMetadata copy timestamps as well under Windows.

Rename windows.h file

GHC has a quirk where to work around the fact that our input file to GCC is in another folder, we add the original input directory to the include search path. This causes a problem since new include paths override system ones. It doesn't however do this for all modes.

For some reasons I have yet to figure out, compiling with cabal works, but not one shot compilation.

Anyway, long story short, when building GHC, the presence of this file names "windows.h" is causing GCC to loop on the includes before eventually terminating. While I'm looking into this it would be really helpful if you could rename this file to something else. That should unblock certain build failures.

See https://ghc.haskell.org/trac/ghc/ticket/14312

removeFile did not remove file or throw errors.

In the following code, in withTemp function, after removeFile fp, the temp file was still there. I tried to use try to catch IOException that may throw by removeFile. I just got Right ().

It is Ubuntu Trusty, ghc 7.8.3, directory 1.2.1.0.

import Network.Curl
import System.Posix.Temp
import System.Directory
import System.IO
import Text.HTML.DOM
import Text.XML
import System.FilePath
import Control.Exception

type PostField = (String, String)

withTemp :: String -> (FilePath -> IO a) -> IO a
withTemp prefix f = do
  tmp <- getTemporaryDirectory
  (fp, h) <- mkstemp $ tmp </> prefix
  hClose h
  finally (f fp) $ removeFile fp

curl :: (CurlBuffer ty) => URLString -> Maybe [PostField] -> IO (Either CurlCode ty)
curl url values = do
  let mPf = fmap (map (\(k, v) -> k ++ "=" ++ v)) values
  (cc, ty) <- withTemp "Cookie" $ \tmp -> withCurlDo $
    let curlOpts_ = [ CurlHttpAuth [HttpAuthAny]
                    , CurlUserPwd ":"
                    , CurlCookieFile tmp
                    , CurlCookieJar tmp
                    , CurlFollowLocation True
                    , CurlUnrestrictedAuth True ]
        curlOpts = case mPf of
                     Nothing -> curlOpts_
                     Just pf -> (CurlPostFields pf) : curlOpts_
    in curlGetString_ url curlOpts
  return $ if cc == CurlOK
              then Right ty
              else Left cc

setModificationTime gives wrong results when cross-compiling

The following test program

module Main where

import qualified System.Directory as D

main :: IO ()
main = do
  u <- D.getModificationTime "test"
  print u
  D.setModificationTime "test" u

compiled with directory 1.2.3.1 from github (commit 1754689), gives the expected result when compiled and run on my amd64 desktop. However, when cross-compiling and running on my raspberry pi, this gives wrong results:

arie@r3 ~ $ ls -l test
-rw-rw-r-- 1 arie arie 0 Aug 17 12:07 test
arie@r3 ~ $ ./setModificationTime-test 
2015-08-17 10:07:50.565253803 UTC
arie@r3 ~ $ ls -l test
-rw-rw-r-- 1 arie arie 0 Jan 10  2004 test

(The getModificationTime is OK: I'm at UTC+2 currently.)

The compiler is ghc-7.10.2 in both cases.

Expected stdout of `createDirectoryIfMissing001` does not match actual output

Expected output

$ cat createDirectoryIfMissing001.stdout
()
createDirectoryIfMissing001.d/a: createDirectory: does not exist (No such file or directory)
()
()
()
()
createDirectoryIfMissing001.d: createDirectory: already exists (File exists)
createDirectoryIfMissing001.d/a: createDirectory: inappropriate type (Not a directory)

Actual output

$ runhaskell createDirectoryIfMissing001.hs 
()
createDirectoryIfMissing001.d/a: createDirectory: does not exist (No such file or directory)
()
()
()
()
()
createDirectoryIfMissing001.d/a: createDirectory: inappropriate type (Not a directory)

Diff

--- ./createDirectoryIfMissing001.stdout    2015-02-21 19:29:03.462825322 -0500
+++ ./createDirectoryIfMissing001.run.stdout    2015-02-21 19:31:28.162325186 -0500
@@ -4,5 +4,5 @@
 ()
 ()
 ()
-createDirectoryIfMissing001.d: createDirectory: already exists (File exists)
+()
 createDirectoryIfMissing001.d/a: createDirectory: inappropriate type (Not a directory)

This appears to have been introduced in 1f11393 while fixing #4. See also #19.

time-1.7 is released

time-1.7 is released. Would you check if it builds OK, and update .cabal file?

Tests don't work with sandboxes

… because the GHC flags are hardcoded in:

HSFLAGS="-package-$db ../dist/package.conf.inplace$HSFLAGS"
HSFLAGS="-optP-include -optP../dist/build/autogen/cabal_macros.h $HSFLAGS"

It would be nice if there was an easy way to get the correct flags from Cabal.

Why is findExecutables private?

Context: I am working on a tool like git such that git hats actually routes the user to an executable named git-hats. One nice feature provided by git is that they will list all of the commands available on your system, even if they are not distributed with git. This means figuring everything on the user's PATH and filtering it down to things that match git-*.

My case described here is pretty much exactly the same, and I need the functionality of findExecutables to make it happen.

Question: Is there a strong reason findExecutables (implemented here) is not exposed? If so, would you recommend duplicating the code? If so, what is going on with the mingw32_HOST_OS macros? Do I need to do any special configuration to use macros like that?

Migrating the tests

Currently, the majority of the tests require the framework that's bundled with the GHC repository, which makes testing directory independently rather difficult. All such tests are located under tests.

@snoyberg has recently started a stub for tests that can be run under Cabal without the GHC test framework. It could use some love right now.

From here, there are two options I can think of:

  • Option A: Port all the tests from GHC framework to the Cabal framework. Figure out a way to integrate the Cabal tests into GHC's test suite (somehow?).
  • Option B: Keep all the tests in the GHC framework. Figure out a way to run these tests without GHC.

I think Option A is more elegant and less difficult than Option B, since in B one would have to embed/install a minimal GHC framework (somehow).

What might be lost in Option A is the fine-grainedness of the tests: from GHC's perspective it will probably be an "all-or-nothing" test.

Questions:

  • Is there any reason for sticking to GHC's test framework?
  • Any strong feelings about which option is better? (I'm biased to A)
  • Is there's a better idea?

createDirectoryIfMissing does not fail on unwritable parent dir

On OSX, using createDirectoryIfMissing to create a new directory inside a directory for which we do not have write permissions does not throw any exception. Of course it should throw an exception, as it does under Linux.

$ mkdir unwritable
$ chmod ugo-w unwritable
$ ghci
> System.Directory.createDirectoryIfMissing True "unwritable/tst"
>

On OSX (10.9.2) this does not fail. Under Linux (albeit with 7.6.3) this does throw an exception as expected:

*** Exception: unwritable/tst: createDirectory: permission denied (Permission denied)

Original Trac Ticket: https://ghc.haskell.org/trac/ghc/ticket/9044

canonicalizePath "." has changed behaviour

The the version of directory that ships with GHC 8.0 RC2 I see canonicalizePath "." == "C:\\Neil\\". On GHC 7.10 it's "C:\\Neil" without the trailing slash. This change of behaviour has broken the Shake test suite, and is not documented in the changelog. If it's an intentional change, it should be in the changelog. If it's unintentional, you still have a small window to revert it.

CC @hvr, who seems to be doing GHC 8.0 release management things.

isSymbolicLink conflicts with System.Posix.Files

Anything that imports System.Posix.Files and System.Directory and uses isSymbolicLink will start failing to build when updated to directory-1.2.6.2. Seems likely that most existing haskell code that uses System.Posix.Files.isSymbolicLink also uses System.Directory

Maybe call the one in System.Directory isSymLink instead?

doesn't build on ghc 8.0 branch tip

theres a missing import of fromMaybe from Data.Maybe,
and even if i fix that theres some other errors such as the following

libraries/directory/System/Directory.hs:1548:10: error:
    • Couldn't match type ‘UTCTime’
                     with ‘time-1.6:Data.Time.Clock.UTC.NominalDiffTime’
      Expected type: Data.Time.Clock.POSIX.POSIXTime
        Actual type: UTCTime
    • In the second argument of ‘setFileTimes’, namely
        ‘(fromMaybe atimeOld atime')’
      In a stmt of a 'do' block:
        setFileTimes
          path' (fromMaybe atimeOld atime') (fromMaybe mtimeOld mtime')
      In the expression:
        do { (atimeOld, mtimeOld) <- fileTimesFromStatus
                                     <$> Posix.getFileStatus path';
             setFileTimes
               path' (fromMaybe atimeOld atime') (fromMaybe mtimeOld mtime') }

libraries/directory/System/Directory.hs:1548:29: error:
    • Couldn't match type ‘time-1.6:Data.Time.Clock.UTC.NominalDiffTime’
                     with ‘UTCTime’
      Expected type: Maybe UTCTime
        Actual type: Maybe Data.Time.Clock.POSIX.POSIXTime
    • In the second argument of ‘fromMaybe’, namely ‘atime'’
      In the second argument of ‘setFileTimes’, namely
        ‘(fromMaybe atimeOld atime')’
      In a stmt of a 'do' block:
        setFileTimes
          path' (fromMaybe atimeOld atime') (fromMaybe mtimeOld mtime')

libraries/directory/System/Directory.hs:1549:10: error:
    • Couldn't match type ‘UTCTime’
                     with ‘time-1.6:Data.Time.Clock.UTC.NominalDiffTime’
      Expected type: Data.Time.Clock.POSIX.POSIXTime
        Actual type: UTCTime
    • In the third argument of ‘setFileTimes’, namely
        ‘(fromMaybe mtimeOld mtime')’
      In a stmt of a 'do' block:
        setFileTimes
          path' (fromMaybe atimeOld atime') (fromMaybe mtimeOld mtime')
      In the expression:
        do { (atimeOld, mtimeOld) <- fileTimesFromStatus
                                     <$> Posix.getFileStatus path';
             setFileTimes
               path' (fromMaybe atimeOld atime') (fromMaybe mtimeOld mtime') }

libraries/directory/System/Directory.hs:1549:29: error:
    • Couldn't match type ‘time-1.6:Data.Time.Clock.UTC.NominalDiffTime’
                     with ‘UTCTime’
      Expected type: Maybe UTCTime
        Actual type: Maybe Data.Time.Clock.POSIX.POSIXTime
    • In the second argument of ‘fromMaybe’, namely ‘mtime'’
      In the third argument of ‘setFileTimes’, namely
        ‘(fromMaybe mtimeOld mtime')’
      In a stmt of a 'do' block:
        setFileTimes
          path' (fromMaybe atimeOld atime') (fromMaybe mtimeOld mtime')

removeDirectory and symlinks

Prelude System.Directory> :!mkdir "a-directory"
Prelude System.Directory> :!ln -s "a-directory" "a-symlink-to-a-directory"
Prelude System.Directory> doesDirectoryExist "a-symlink-to-a-directory"
True
Prelude System.Directory> removeDirectory "a-symlink-to-a-directory"
*** Exception: a-symlink-to-a-directory: removeDirectory: inappropriate type (Not a directory)

directory-1.2.6.1 fails to install

Failed to install directory-1.2.6.1
Last 10 lines of the build log ( /home/travis/build/kolmodin/binary/.cabal-sandbox/logs/directory-1.2.6.1.log ):
[1 of 1] Compiling Main             ( /tmp/directory-1.2.6.1-2587/directory-1.2.6.1/dist/dist-sandbox-29f73198/setup/setup.hs, /tmp/directory-1.2.6.1-2587/directory-1.2.6.1/dist/dist-sandbox-29f73198/setup/Main.o )
Linking /tmp/directory-1.2.6.1-2587/directory-1.2.6.1/dist/dist-sandbox-29f73198/setup/setup ...
Configuring directory-1.2.6.1...
Warning: The 'build-type' is 'Configure' but there is no 'configure' script.
setup: configure script not found.

Looks like build-type: Configure but there is no configure file included in the package.

add rename function without directory/file distinction

On both Windows and Posix platforms, the invocation of the underlying rename function is identical, so the value of explicitly choosing either the directory or file API is diminished. In my specific use case, I wanted to implement renameSync but had to swipe the System.Directory's implementation instead of being able to rely on the System.Directory module.

In addition, checking for a file or directory in advance opens a potential race condition and blocks usage of rename against non-file, non-directory nodes such as devices.

For my use case, a rename function which ignores the directory/file distinction would have solved the problem.

Add ability to get file/folder properties

Is it possible to add a function like:

getProperties :: FilePath -> IO Properties

data Properties = Properties {
  name :: String
  type :: String
  size :: Integer
  etc...
}

Thank you!

canonicalizePath is no longer canonical for directories (trailing slashes)

It used to be the case that canonicalizePath for directories would return the directory without the trailing slash, irrespective of whether the directory was given with or without the trailing slash. As of some version, but certainly including 1.2.6 and still in 1.2.7.1 the result sometimes includes a trailing slash and sometimes does not. This violates the property that the result be canonical.

$ ghci -package directory-1.2.7.1
> :m System.Directory
> canonicalizePath "./"
"/home/duncan/"
> canonicalizePath "."
"/home/duncan"
> canonicalizePath "./foo/"
"/home/duncan/foo/"
> canonicalizePath "./foo"
"/home/duncan/foo"

This canonical property is important, lots of code relies on it. As an example of the kind of bug it causes:

cabal new-build ./
Unknown build target './'.
The project has no package directory './'.
Perhaps you meant the package directory './'?

This happens because this code relies on the canonical property to match up packages that are known to live at various locations with a directory given by the user. Since one code path happens to call canonicalizePath with a trailing slash and another without then there is no match and the confusing error.

canonicalizePath hangs when used on a file in an sshfs share (threaded RTS only)

Tested on GHC 7.10.2 and directory 1.2.2.0 on OS X.

To reproduce this issue first mount a sshfs share (I used a server on a quite high latency link).

sshfs server:haskell/Haxl haskell/Haxl

Check that the share is working and then compile and run something like this with --threaded

module Main (main) where

import System.Directory (canonicalizePath)

main :: IO ()
main = canonicalizePath "/Users/hamish/haskell/Haxl/haxl.cabal" >>= print

(where the file haxl.cabal is a file that exists on the server.)

The process hangs.

Changing

foreign import ccall unsafe "realpath" c_realpath

to

foreign import ccall safe "realpath" c_realpath

seems to make the problem go away.

`findExecutable` and `findFile` could be lazier

$ touch "file.txt"
$ stack ghci
...
GHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help
Ok, modules loaded: none.
λ> import System.Directory
λ> findFile ("." : undefined) "file.txt"
*** Exception: Prelude.undefined
λ> findFile ("." : []) "file.txt"
Just "./file.txt"

GHC-7.6 didn't use to have this problem but the behaviour changed with 7789d1c.

getModificationTime on Windows should give a better error message

GHCi, version 7.10.2: http://www.haskell.org/ghc/  :? for help
Prelude> import System.Directory
Prelude> readFile "foo"
*** Exception: foo: openFile: does not exist (No such file or directory)
Prelude System.Directory> getModificationTime "foo"
*** Exception: getFileAttributesExStandard: does not exist (The system cannot find the file specified.)

Error message should mention the file you are trying to use.

@since not rendered properly on Hackage

The @SInCE tags don't appear to be rendered properly on Hackage. I think that the should be shown as "Since: 1.2.3.0", in italics, since that's what's done for modules such as System.Process. Instead, they're shown as "@SInCE 1.2.3.0", using a regular font.

canonicalizePath doesn't respect directory substitutions on Windows

Related to mrkkrp/path-io#30

If we use substituted paths (using subst shell command) we may create a new Windows drive for specific paths on other drives. This is called "directory substitution". It's used often in production environments. As we use it on Jenkins building farm. We try to overcome Windows max. path length issue with substituting long paths into smaller on a substituted drive.
Here is an example of P:

D:......> subst P: .
P:>stack repl --package directory-1.3.1.4
...
Prelude> import System.Directory
Prelude> canonicalizePath "."
"D:\Work\long\builder\jenkins\home\workspace\work_master-IH6I4ZJQUG22JDFTMS624VMTMO5APB7UUFMDD7ZRLLQLR32Y2H5A\work"

This is not correct and it should return the path in the correct drive, like:

"P:\work"

Behavior of `getHomeDirectory` and/or `canonicalizePath` is inconsistent across GHC versions

Here is the test:

https://github.com/mrkkrp/path-io/blob/master/tests/Main.hs#L116

It succeds with 7.10, but fails with 7.8 and 8.0:

https://travis-ci.org/mrkkrp/path-io/jobs/110565920#L381

At first I decided to “forgive” 7.8 and added some CPP to skip that test there, but now I added 8.0 to build matcix and this thing again throws something unexpected. getHomeDir uses getHomeDirectory and canonicalizePath, so the only thing it can throw in the setting of that test is isDoesNotExistError. Any comment?

`findFile` edges case with absolute paths on Windows

The examples below where findFile returns Nothing are surprising, and if possible I think they should return the obvious path.

Prelude> import System.Directory
Prelude System.Directory> doesFileExist "C:\\tmp\\Test.hs"
True
Prelude System.Directory> findFile [] "C:\\tmp\\Test.hs"
Nothing
Prelude System.Directory> findFile ["C:\\"] "tmp\\Test.hs"
Just "C:\\tmp\\Test.hs"
Prelude System.Directory> findFile [] "\\tmp\\Test.hs"
Nothing
Prelude System.Directory> findFile ["\\"] "tmp\\Test.hs"
Just "\\tmp\\Test.hs"
Prelude System.Directory> setCurrentDirectory "C:\\tmp"
Prelude System.Directory> findFile ["."] "Test.hs"
Just ".\\Test.hs"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.