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).
Related
I am knitting markdown code initiated from a database command button with a shell command to execute a batch file. The goal here is to knit the file into a directory specific to the database record. Batch file execution currently looks like this:
"Rscript.exe" -e "library('knitr'); rmarkdown::render('MyCode.Rmd', output_file="MyRMD.html")"
Inside the rmd file I create a variable (say 'out_dir') that contains the directory string where I want the output file to be stored. Is there any way I can use this variable to direct where knitr will store the rendered file? Other than YAML parameters, can you control knitr output options from within the code?
This wasn't the approach I was trying to accomplish, but the workaround was to build a front end script to the markdown document that did the necessary pre-processing and then passed the values using "output_file", "output_dir" and a "params()" list matching the YAML header in the rmd (Note this part is not necessary in solving the original question, but since I took this approach it makes it handy to pull even more pre-processing code out of the rmd and into the front end passing values through params). So the front end initiates the knit:
rmarkdown::render("MyCode.Rmd",
params = list(P1 = p1, P2 = p2),
output_file = 'MyRMD.html',
output_dir = 'Dir_From_Database_Record')
And just for completeness the markdown rmd YAML header from MyCode.RMD looks like:
output: html_document
params:
P1: NA
P2: NA
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)
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
I am new to Powershell but have had experience with various programming languages including dBase III, basic, Fortran (shows my age). I am a musician and launch MP3 files as an accompanyment when I perform live, somewhat like karaoke. I have about 45 different MP3s that I use. I like to change the sequence of the songs that I perform, from time to time and this requires renaming the MP3 file names with a preceeding sequence number. The file names take on the form: "01 songnameA.mp3", "02 songnameB.mp3", "03 songnameC.mp3", etc. I also repeat songs so there might be an "09 songnameA.mp3" in the folder that I play back from. To do this, I typically create a text file that lists the songs in the order that I want to perform them. Each line in the text file has the form "01 Songname X" but no MP3 extension. I then manually copy the mp3 files into a folder and then edit the names applying a sequence number according to the text file. This is time-consuming.
I have created a Powershell script (version 2) that creates an array of the text file content and an array of the unnumbered MP3 song files. The script creates a 3rd array containing numbered MP3 filenames according to the sequence in the text file. This array does work and I can easily display the list of items in it which have the form "01 SongnameX.mp3". However, I have been unable to copy this array of MP3 filenames with a preceeding sequence number into another folder. I don't know how many variations of the "Copy-Item" statements I have tried but nothing works. The name of the array that contains the filenames is $nsfarray (new song file array). The command I am presently using:
$nsfarray | copy-item -Destination C:\temp
Returns the following error message:
Copy-item : Cannot find path 'C:\Users\My HP\Documents\My Scripts\01 A Good Time.mp3' because it does not exist.
The path is the default path that I use to run Powershell but somehow the MP3 file names get appended to it. The "01 A Good Time.mp3" is the first item in the $nsfarray. I know I am missing something here. Any suggestions would be appreciated.
This is really crude but the issue I see with your input file is that it obviously does not exactly match the real file name that you are looking to copy. So with that in mind lets try this on for size.
$musicPath = "c:\music"
$destinationPath = "c:\songset"
$nsfarray = "01 Age of Aquarius"
$nsfarray | ForEach-Object{
If($_ -match '^\d+ *(?<BaseName>.*)'){
Copy-Item "$musicPath\$($Matches.BaseName).mp3" -Destination "$_.mp3"
}
}
Work with explicit paths: $musicPath and $destinationPath so that we do not have to rely on our current location in PowerShell. Then we navigate each value in the array, which I have populated with one example. Now we need to extract the real file name away from your set list number. Using regex we return the part of the string that is not the beginning numbers and spaces and take everything after that.
After we simply copy the file that exists in the $musicPath folder that has the name "Age of Aquarius.mp3", which should be the real file, and copy it to the $destinationPath as "01 Age of Aquarius.mp3", which is how you want the file for your gig.
Clarification
After answering this and looking back at the question I think there is a chance I didn't understand it right. Please update the question if this is not the right way to address this. The core of your problem, if nothing else, is that you are not specifying a proper file path for the mp3s. You need to use the proper source folder and append the mp3 to the string.
In the directory that I am working, I have many files file1 file2 file3 etc. I don't know the names of the files in advance, however I know that they are the only files starts with A , for example A*.txt. How can I pass file names in an array to MATLAB?
Just use
files=dir('./A*.txt')
files is a structure, so you can acces the filenames with
files(Index).name
If you want all the filenames in an easy-to-use cellarray, try
cellarray = {files(:).name}
Here's a short and simple answer:
filenames = dir('A*')
This assumes you want to return files in the present directory beginning with "A", you could build off this example as needed though.
Your question is a bit broad, so I'll make a few assumptions, namely that you don't mind cell arrays and that the files are of a specific extension. With that said, if you want to do it in a general manner and you know the extension, you can do:
EDIT: in light of the fact that you know the first part of the filename, you can modify your call to the dir function reflect that:
%have the part of the filename you know here, in your question that being 'A'
file_prefix = 'A';
file_path = pwd;
%this will get all of the .txt files. Put the extension you want here
file_names = dir(strcat(file_path,filesep,file_prefix,'*.txt'));
fnames = cell(length(file_names), 1);
for i=1:length(file_names)
fnames{i} = file_names(i).name;
end
This will give a cell array of strings containing all of the filenames of the specified extension, which you can pass to whatever needs the filenames. You can generalize this to get the file names from any directory by specifying the path (instead of using pwd, which gets the contents of the current directory)