开发者

How to get list of directories in Lua

I need a list of directory in LUA

Suppose I have a directory path as "C:\Program Files"

I need a list of all the folders in that particular path and how to search any particular folder in that list.

Example

Need a list of all the folder in path "C:\Program Files"

Below are folder name in the above path

  1. test123

  2. test4567

  3. folder 123

  4. folder 456

  5. folder 456 789

    Need to get the above in a list and then have to search for a particular string like folder 456 in folder 456 789 only.

Have Tried below code. Something I am missing below:-

local function Loc_Lines( str )
--
local ret= {}   -- 0 lines

while str do
    local _,_,line,tail= string.find( str, "(.-)\n(.+)" )
    table.insert( ret, line or str )
    str= tail
  Print (str)
end

return ret
end


local function Loc_ShellCommand( cmd )
--
local str= nil

    --
    local f= io.popen( cmd )    -- no command still returns a handle :(
     if f then
开发者_StackOverflow
        str= f:read'*a'
    Print(str)
        f:close()
    end
    
    if str=="" then   -- take no output as a failure (we can't tell..)
    Print("hi")
        str= nil
    end
 
-- Remove terminating linefeed, if any (eases up one-line analysis)
--
if str then
    if string.sub( str, -1 ) == '\n' then
        str= string.sub( str, 1, -2 )
    end
end

return str
 end


 local function Loc_DirCmd( cmd )

 Print(cmd)

  local str= Loc_ShellCommand( cmd )



 return Loc_Lines(str)
 end


local function Loc_DirList( dirname )

 local ret= {}
  
    local lookup= {}

   local tbl= Loc_DirCmd( "dir /AD /B "..dirname )   -- only dirs

    -- Add slash to every dir line
    --
    for i,v in ipairs(tbl) do
        table.insert( ret, v..'\\' )
        lookup[v]= true
    end       

    
    -- Return with forward slashes
    --
    if true then
        for i=1,table.getn(ret) do
            ret[i]= string.gsub( ret[i], '\\', '/' )
     Print (ret[i])
        end
    end
  

   return ret
 end


 Loc_DirList("C:\\Program Files\\")


I hate having to install libraries (especially those that want me to use installer packages to install them). If you're looking for a clean solution for a directory listing on an absolute path in Lua, look no further.

Building on the answer that sylvanaar provided, I created a function that returns an array of all the files for a given directory (absolute path required). This is my preferred implementation, as it works on all my machines.

-- Lua implementation of PHP scandir function
function scandir(directory)
    local i, t, popen = 0, {}, io.popen
    local pfile = popen('ls -a "'..directory..'"')
    for filename in pfile:lines() do
        i = i + 1
        t[i] = filename
    end
    pfile:close()
    return t
end

If you are using Windows, you'll need to have a bash client installed so that the 'ls' command will work - alternately, you can use the dir command that sylvanaar provided:

'dir "'..directory..'" /b /ad'


Take the easy way, install lfs. Then use the following constructs to find what you need:

require'lfs'
for file in lfs.dir[[C:\Program Files]] do
    if lfs.attributes(file,"mode") == "file" then print("found file, "..file)
    elseif lfs.attributes(file,"mode")== "directory" then print("found dir, "..file," containing:")
        for l in lfs.dir("C:\\Program Files\\"..file) do
             print("",l)
        end
    end
end

notice that a backslash equals [[\]] equals "\\", and that in windows / is also allowed if not used on the cmd itself (correct me if I'm wrong on this one).


 for dir in io.popen([[dir "C:\Program Files\" /b /ad]]):lines() do print(dir) end

*For Windows

Outputs:

Adobe
Bitcasa
Bonjour
Business Objects
Common Files
DVD Maker
IIS
Internet Explorer
iPod
iTunes
Java
Microsoft Device Emulator
Microsoft Help Viewer
Microsoft IntelliPoint
Microsoft IntelliType Pro
Microsoft Office
Microsoft SDKs
Microsoft Security Client
Microsoft SQL Server
Microsoft SQL Server Compact Edition
Microsoft Sync Framework
Microsoft Synchronization Services
Microsoft Visual Studio 10.0
Microsoft Visual Studio 9.0
Microsoft.NET
MSBuild
...

Each time through the loop you are given a new folder name. I chose to print it as an example.


I don't like installing libraries either and am working on an embedded device with less memory power then a pc. I found out that using 'ls' command lead to an out of memory. So I created a function that uses 'find' to solve the problem.

This way it was possible to keep memory usage steady and loop all the 30k files.

function dirLookup(dir)
   local p = io.popen('find "'..dir..'" -type f')  --Open directory look for files, save data in p. By giving '-type f' as parameter, it returns all files.     
   for file in p:lines() do                         --Loop through all files
       print(file)       
   end
end


IIRC, getting the directory listing isn't possible with stock Lua. You need to write some glue code yourself, or use LuaFileSystem. The latter is most likely the path of least resistance for you. A quick scan of the docs shows lfs.dir() which will provide you with an iterator you can use to get the directories you are looking for. At that point, you can then do your string comparison to get the specific directories you need.


You also install and use the 'paths' module. Then you can easily do this as follow:

require 'paths'

currentPath = paths.cwd() -- Current working directory
folderNames = {}
for folderName in paths.files(currentPath) do
    if folderName:find('$') then
        table.insert(folderNames, paths.concat(currentPath, folderName))
    end
end

print (folderNames)

-- This will print all folder names

Optionally, you can also look for file names with a specific extension by replacing fileName:find('$') with fileName:find('txt' .. '$')

If you're running on a Unix-based machine you can get a numerically-sorted list of files using the following code:

thePath = '/home/Your_Directory'
local handle = assert(io.popen('ls -1v ' .. thePath)) 
local allFileNames = string.split(assert(handle:read('*a')), '\n')

print (allFileNames[1]) -- This will print the first file name

The second code also excludes files such as '.' and '..'. So it's good to go!


Don't parse ls, it's evil! Use find with zero-terminated strings instead (on linux):

function scandir(directory)
    local i, t = 0, {}
    local pfile = assert(io.popen(("find '%s' -maxdepth 1 -print0"):format(directory), 'r'))
    local list = pfile:read('*a')
    pfile:close()
    for filename in s:gmatch('[^\0]+')
        i = i + 1
        t[i] = filename
    end
    return t
end

WARNING: however, as an acceped answer this apporach could be exploited if directory name contain ' in it. Only one safe solution is to use lfs or other special library.


Few fixes of val says Reinstate Monica solution:

function scandir(directory)
    local pfile = assert(io.popen(("find '%s' -mindepth 1 -maxdepth 1 -type d -printf '%%f\\0'"):format(directory), 'r'))
    local list = pfile:read('*a')
    pfile:close()

    local folders = {}

    for filename in string.gmatch(list, '[^%z]+') do
        table.insert(folders, filename)
    end

    return folders
end

Now it filters by folders, excludes dir itself and prints only names.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜