Good evening,
I am currently working on a programm that takes information from a file into a Database, for testing purposes I used to open Testfiles in the classical way via IO:
function reader (file, delimeter)
local f = io.open(file)
for line in f:lines() do
lines[count] = splitty(line, delimeter)
count = count + 1;
end
end
(this part also containes the first part of a splitter)
But in the actual environment, the database programm imediatly moves the file in another directory with a name change to, for example this:
$30$15$2016$09$26$13$27$24$444Z$.Pal.INV.csv
Now I know the directory but I can't really predict the name, so I wanted to know if there might be a way to open files without knowing their name.
(and delete them after reading them)
I had ideas to use a modified link:
local inputFile = "D:\\Directory\\(*all)"
but it failed.
Other aviable information:
The system is until now only planned on Windows PCs.
The directory will always only contain the one file that is to ready, no other files.
You can use the lfs.dir iterator from LuaFileSystem to iterate through the contents of the directory. A small example:
local lfs = require("lfs")
local path = "D:\\Directory\\" -- Your directory path goes here.
for filename in lfs.dir(path) do
print(filename) -- Work with filename, i will just print it
end
If you keep a record of the files you will be able to know which one is the new one. If it is only one file, then it will be easier, you can just check the extension with a string function. From what i remember the iterator includes .. and .. lfs documentation can be found here.
-- directory name and file name should consist of ASCII-7-bit characters only
local dir = [[C:\Temp\New Folder]]
local file = io.popen('dir /b/s/a-d "'..dir..'" 2>nul:'):read"*a":match"%C+"
if not file then
error"No files in this directory"
end
-- print the file name of first file in the directory
print(file) --> C:\Temp\New Folder\New Text Document.txt
Related
I am new to lua to trying to understand and put pieces to together and looking out for some help.
I have gone through the existing articles on lua file looping but unable to get the desired output.
Question - I have a folder with files, Folder path - "D:\Test_Files\Outbound\Client\final"
Files in the folder with extension - .txt
Trying to :
Get the count of files in the folder(in this case "final" folder).
Read every file, building a loop something similar to this:
list = {}
for i=0,(#Totalfilecount) do
local fr = io.open('D:\Test_Files\Outbound\Client\final\'..filename.,'rb')
local f = fr.read('*.txt')
Customfunction(f) -- Passing file content to customfunction to apply business logic.
end
Questions :
How to get file count from a directory?
How to read the directory to check if the files with "*.txt" exist?
How to use table list to store each file name and read through the loop?
How to read each file via loop and pass the value to function "Customfunction(f)"?
Code is expected to run on windows. Please share suggestions in pure lua without using external file system functions such as 'lfs' as we do not like to import external functions.
Any Suggestions/help will be greatly appreciated!
You can't (at least shouldn't) do this without extensions to Lua. To accomplish this, you have to download LuaFileSystem library. You can do it using LuaRocks:
$ luarocks install luafilesystem
Use library as such:
require "lfs"
function dirtree(dir)
assert(dir and dir ~= "", "Please pass directory parameter")
if string.sub(dir, -1) == "/" then
dir=string.sub(dir, 1, -2)
end
local function yieldtree(dir)
for entry in lfs.dir(dir) do
if entry ~= "." and entry ~= ".." then
entry=dir.."/"..entry
local attr=lfs.attributes(entry)
coroutine.yield(entry,attr)
if attr.mode == "directory" then
yieldtree(entry)
end
end
end
end
return coroutine.wrap(function() yieldtree(dir) end)
end
An example use of code above:
for filename, attr in dirtree("D:\Test_Files\Outbound\Client\final") do
print(attr.mode, filename)
end
You have to check does extension equal to txt. To read file extension use this snippet:
function GetFileExtension(path)
return path:match("^.+(%..+)$")
end
So, to answer your question(s), you can get amount of files in directory just by counting elements in array returned in dirtree. To answer second question, just use code from the post. Table that you want is returned by dirtree(), but you may want to extract only .txt files from it. To read a file, just check other SO answers. You've got given name (in array), so use it.
EDIT: You can parse result of dir and ls command to get directory listing, but you shouldnt. Althrough this way you wouldn't need to install any libraries, your code is going to be heavily OS-depedent.
Adding libraries to your code isn't so bad. Hacking things is worse.
(Not sure file extension extracting function is going to work. I didn't make dirtree code used in this post, it belongs to David Kastrup)
I could find out here, how can I create a new file with pure Lua code. The next snippet should do it theoretically:
file = io.open("test.txt", "w")
file:write("Hello World")
file:close()
However, I can't find the created file in the folder of the source code file. Where does it save the file - if it even creates a new one?
If not, what's the way of doing it?
It will use the processes current working directory (CWD) which is going to wherever your shell/environment was when you ran the script.
I want to save my files within a folder but the issue which raising is that my files are storing outside of the folder which is annoying. I am sharing what I have done so far.
-- get raw path to app's Temporary directory
local doc_path = system.pathForFile( "", system.DocumentsDirectory )
-- change current working directory
local success = lfs.chdir( doc_path ) -- returns true on success
local new_folder_path
if success then
lfs.mkdir( "MyNewFolder" )
new_folder_path = lfs.currentdir() .. "/MyNewFolder"
end
local filePath = system.pathForFile( dataFileName , new_folder_path )
r = media.newRecording(filePath)
--print("new recording has been started with a name"..dataFileName)
r:startRecording()
but my recorded file is out of this newly created folder
can someone help me here?
I searched out and finally got the answer that the problem.This is how to create a new recording in specified folder
r = media.newRecording( new_folder_path.."/"..dataFileName )
This line would automatically create a file in this folder as mentioned in the question.
system.pathForFile() only creates a file automatically when the second argument is a base directory like system.DocumentsDirectory (as it is clearly mentioned in the documentation that the second argument is constant and it should be only any base directory).
so if you want to create a new file r want to find the path of the file you would append folder name before the file name like my folder/my file
Hope this would help
here's what i've been trying to do with lua.
i have a ton of pictures i transfer back and forth between 2+ computers. I always end up having multiple copies of pictures. I would like my lua code to get all the file names from the folder and allow me to input a search filter (a file name) that the program will compare to the list of file names and let me know if it's already in the folder or not. I've been racking my brain for the past few days to get this to work but no luck, all i've got so far is the text box made and i can get lua to return data about the files in the folder with this:
local f = io.popen("dir \"C:\\mydir\\\"")
if f then
print(f:read("*a"))
else
print("failed to read")
end
Standard Lua has no mechanism for doing what you want. It's a scripting language designed for embedded systems, unlike Python which has a massive, feature-rich runtime library.
If you want to do this, you should consider using the Lua FileSystem module. It can get directory lists and that sort of thing.
How to get an array of filenames from some folder:
local function get_files(path, prepend_path_to_filenames)
if path:sub(-1) ~= '\\' then
path = path..'\\'
end
local pipe = io.popen('dir /b/a-d "'..path..'*.*" 2> nul')
local output = pipe:read'*a'
pipe:close()
-- If your file names contain national characters
-- output = convert_OEM_to_ANSI(output)
local files = {}
for filename in output:gmatch'[^\r\n]+' do
if prepend_path_to_filenames then
filename = path..filename
end
table.insert(files, filename)
end
return files
end
local array_of_files = get_files('C:\\mydir', false)
for _, fn in ipairs(array_of_files) do
print(fn)
end
Empty array will be returned in case of path not exists (no distinction between empty folder and non-existing folder).
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.