doesFileExist not finding files that exist - haskell

So I have a directory, /test, and in it are the following files:
test.txt
BasicLoop.vm
FibonacciSeries.vm
StackTest.vm
test.vm
I'm trying to read all the .vm files into one massive string, and in order to do so I thought to use filterM doesFileExist dir where dir is the result of getDirectoryContents, to remove directories and symlinks and whatever, but when I test it, the result of that filter is just BasicLoop.vm and test.vm. None of them are empty, and they show up when I peek at the contents of dir, so they clearly do exist. Why does the function say they don't?

Why does the function say they don't?
Because getDirectoryContents returns the file and directory names, not the full filepath. To see that, try something like:
λ:> getDirectoryContents "test"
["data","..","test.dats","."]

Related

The system cannot find the file specified - WinError 2

Upon looping a directory to delete txt files ONLY - a message is returned indicating The System cannot find the file specified: 'File.txt'.
I've made sure the txt files that I'm attempting to delete exist in the directory I'm looping. I've also checked my code and to make sure it can see my files by printing them in a list with the print command.
import os
fileLoc = 'c:\\temp\\files'
for files in os.listdir(fileLoc):
if files.endswith('.txt'):
os.unlink(files)
Upon initial execution, I expected to see all txt files deleted except for other non-txt files. The actual result was an error message "FileNotFoundError: [WinError 2] The system cannot find the file specified: 'File.txt'.
Not sure what I'm doing wrong, any help would be appreciated.
It isn't found because the the path you intended to unlink is relative to fileLoc. In fact with your code, the effect is to unlink the file relative to the current working directory. If there were *.txt files
in the cwd then the code would have unfortunate side-effects.
Another way to look at it:
Essentially, by analogy, in the shell what you're trying to do is equivalent to this:
# first the setup
$ mkdir foo
$ touch foo/a.txt
# now your code is equvalent to:
$ rm *.txt
# won't work as intended because it removes the *.txt files in the
# current directory. In fact the bug is also that your code would unlink
# any *.txt files in the current working directory unintentionally.
# what you intended was:
$ rm foo/*.txt
The missing piece was the path to the file in question.
I'll add some editorial: The Old Bard taught us to "when in doubt, print variables". In other words, debug it. I don't see from the OP an attempt to do that. Just a thing to keep in mind.
Anyway the new code:
Revised:
import os
fileLoc = 'c:\\temp\\files'
for file in os.listdir(fileLoc):
if file.endswith('.txt'):
os.unlink(os.path.join(fileLoc,file))
The fix: os.path.join() builds a path for you from parts. One part is the directory (path) where the file exists, aka: fileLoc. The other part is the filename, aka file.
os.path.join() makes a whole valid path from them using whatever OS directory separator is appropriate for your platform.
Also, might want to glance through:
https://docs.python.org/2/library/os.path.html

Message <class WindowError> in reading recursavely a directory

I started to study Python 3 and, for fun, I'm trying to code a small software that, from a directory root, read recursively the filesystem and stores some informations about files in a csv file, but I'm receiving this exception
<class 'WindowsError'>
that I don't understand well. It looks like a problem of import, but I use this code
def buildsinglefile(currentfile, directory):
x = SingleFile(currentfile, directory)
return x
def walkdir(root_path):
# traverse root directory, and list directories as dirs and files as files
readfiles = []
print(root_path)
for root, dirs, files in os.walk(root_path):
path = root.split(os.sep)
for file in files:
print('file>'+file)
row = buildsinglefile(file, path ).tocsv()//here exception
readfiles.add(row)
for directory in dirs:
walkdir(directory)
All that I'm doing is (in Java developer state of mind :) ) in the main file (not inside a class):
parsing filesystem with os.walk
call the function buildsinglefile that creates an Object
put this object in a list
The point 2 is uncorrect, but I don't understand why.
Do you think everything?
Thank you

Is there a way to undo a batch-rename of file extensions?

Ok so I kinda dropped the ball. I was trying to understand how things work. I had a few html files on my computer that I was trying to rename as txt files. This was strictly a learning exercise. Following the instructions I found here using this code:
for file in *.html
do
mv "$file" "${file%.html}.txt"
done
produced this error:
mv: rename *.html to *.txt: No such file or directory
Long story short I ended up going rogue and renaming the html files, as well as a lot of other non html files as txt files. So now I have files labeled like
my_movie.mp4.txt
my_song.mp3.txt
my_file.txt.txt
This may be a really dumb question but.. Is there a way to check if a file has two extensions and if yes remove the last one? Or any other way to undo this mess?
EDIT
Doing this find . -name "*.*.txt" -exec echo {} \; | cat -b seems to tell me what was changed and where it is located. The cat -b part is not necessary but I like it. This still doesn't fix what I broke though.
I'm not sure if terminal can check for extensions "twice", but you can check for . in every name an if there's more than one occurence of ., then your file has more extensions. Then you can cut the extension off with finding first occurence of . in a string when going backwards... or last one if checking characters in string in a normal way.
I have a faster option for you if you can use python. You can strip the extension with:
for file in list_of_files:
os.rename(file,os.path.splitext(file)[0])
which can give you from your file.txt.txt your file.txt
Example:
You wrote that your command tells you what has changed, so just take those changed files and dump them into a file(path to file per line). Then you can easily run this:
with open('<path to list>') as f:
list_of_files = f.readlines()
for file in list_of_files:
os.rename(file.strip('\n'), os.path.splitext(file.strip('\n'))[0])
If not, then you'd need to get the list from python:
import os
results = []
for root, folder, filenames in os.walk(<your path to folder>):
for filename in filenames:
if filename.endswith('.txt.txt'):
results.append(os.path.join(root, filename))
With this you got a list of files ending with .txt.txt like this <your folder>\\<path_to_file>.
Get a path to your directory used in os.walk() without folder's name(it's already in list) so it'll be like this:
e.g. os.walk('/home/me/directory') -> path='/home/me/' and res is item already in a list, which looks like directory/...
for res in results:
path = '' # set the path here
file = os.path.join(path,r)
os.rename(file, os.path.splitext(file)[0])
Depending on what files you want to find change .txt.txt in if filename.endswith('...') to whatever you like and os.rename() will take file's name without extension which in your case means it strips the additional extension you don't want to have.

Haskell compilation with an input file, error openFile: does not exist (No such file or directory)

I apologize if this is a simple question.
I have specified an input file which is in the same directory of the code source file.
isprime :: Int -> [Int] -> Bool
isprime ...
main = do
handle <- openFile "primes-to-100k.txt" ReadMode
contents <- hGetContents handle
i <- getLine
print $ isprime (read i::Int) $ map (\x->read x::Int) $ lines contents
hClose handle
The code runs well when I use "runhaskell Q111.hs" in shell,
but when I compile it with "ghc --make Q111.hs and run, I got an error message
Q111: primes-to-100k.txt: openFile: does not exist (No such file or directory)
logout
The point is that the code runs well with ghci and runhaskell, but the executable can't find the input txt.
Do I have to provide the input txt to compiler using someway?
How are you running the executable? The text file would have to be in the directory you run the program from, which may or may not be where the program is. If you are running ./Q111 from the command line, or if you are double-clicking Q111.exe in Windows, then the text file must be in the same folder as the executable. If you are in a different directory on the command line, then the text file would have to be wherever your current directory is, and not the directory where the executable is.
EDIT: Just saw from your other comment that you are on OS X, and (I assume) are double-clicking the program. From what you said I guess that OS X sets the current directory of such-executed programs to be your home. If you want to get the directory of your program, see the answers to this question. If you use the FindBin package they mention:
main = do
exedir <- getProgPath
handle <- openFile (exedir ++ "/primes-to-100k.txt") ReadMode
...
Try the curdDir <- getCurrentDirectory and paths <- getDirectoryContents and check the paths. If it contains the filename, the path is right(and try using contents <-readFile "file" for simpler programs, but this isn't neccessary).
Edit:
...and use isexist <- doesFileExist "f" for checking the existence.

create a list of files to be deleted

I am working on a search-and-destroy type program which I need it to do is search all directories with a certain file-name and append them to a list. after that delete all those files...not objects in list or the list...
import os
file_list=[]
for root, dirs, files in os.walk(path-to-dir'):
for f_name in files:
if f_name.startswith("file-name"):
file_list.append(f_name)
I could write up to appending part of the code but I don't know next...
Some help please
To remove a file from your computer, use os.remove(). It takes full path to the file as it's parameter, so instead of calling os.remove("infectedFile.dll") you would call os.remove("C:/program files/avira/infectedFile.dll")
So your file_list should contain full paths to the files, and then just call:
for file in file_list:
os.remove(file)
Modify your file_list.append(f_name). The f_name is only a bare name. You need to add the path to the file name in the time of processing, because you do not know where the file was found in the directory hierarchy:
file_list.append(os.path.join(root, f_name))
The root variable contains the path during walking.
To make check whether your code works, just print the content of the list:
print('\n'.join(file_list))
Or you can do it in the loop to get ready for the later part:
for fname in file_list:
print(fname)
Then you just add the os.remove(fname) to remove the file name:
for fname in file_list:
print('removing', fname)
os.remove(fname)

Resources