Linux 递归列出目录内容,并检查文件是否为目录
我正在努力学习组装,所以如果我的问题是基本的,请耐心听我说 下面的代码扫描一个目录并打印出其中的所有文件和目录,除了那些以点开头的文件和目录。它似乎工作得很好 但是,一旦我取消对call scandir行的注释以启用递归,它就会打印出一长串重复的文件名,详情见下文 另外,我想用一种方法来测试文件是否为目录。我该怎么做?据我所知,目前这还不是问题所在,因为如果它不是一个目录,那么对scandir的调用只会返回而不做任何事情,但是检查可能会在以后变得很重要,而且不管怎样,这似乎是一件好事Linux 递归列出目录内容,并检查文件是否为目录,linux,assembly,x86,nasm,Linux,Assembly,X86,Nasm,我正在努力学习组装,所以如果我的问题是基本的,请耐心听我说 下面的代码扫描一个目录并打印出其中的所有文件和目录,除了那些以点开头的文件和目录。它似乎工作得很好 但是,一旦我取消对call scandir行的注释以启用递归,它就会打印出一长串重复的文件名,详情见下文 另外,我想用一种方法来测试文件是否为目录。我该怎么做?据我所知,目前这还不是问题所在,因为如果它不是一个目录,那么对scandir的调用只会返回而不做任何事情,但是检查可能会在以后变得很重要,而且不管怎样,这似乎是一件好事 [SECT
[SECTION .data]
DirName db 'test', 0
[SECTION .bss]
[SECTION .text]
extern puts ; Externals from glibc standard C library
extern opendir ; Externals from dirent.h
extern closedir
extern readdir
global main
scandir:
pushad ; Save caller's registers
push eax ; Directory is passed in eax
call opendir ; Open directory
add esp, 4
cmp eax, 0 ; opendir returns 0 on failure
je .done
mov ebx, eax ; Move directory handle to ebx
.read:
push ebx ; Push directory handle
call readdir ; Read a file from directory
add esp, 4 ; Clean up the stack
cmp eax, 0 ; readdir returns 0 on failure or when done
je .close
add eax, 11 ; File name is offset at 11 bytes
mov cl, byte [eax] ; Get first char of filename
cmp cl, 46 ; Ignore files and dirs which begin with a dot
je .read ; (., .., and hidden files)
;call scandir ; Call scandir recursively
; If file is not a dir opendir will simply fail
push eax
call puts
add esp, 4
jmp .read
.close:
push ebx ; Close directory
call closedir
add esp, 4
jmp .done
.done:
popad ; Restore caller's registers
ret
main:
push ebp ; Set up stack frame for debugger
mov ebp, esp
push ebx ; Must preserve ebp, ebx, esi and edi
push esi
push edi
; start
mov eax, DirName
call scandir
; end
pop edi ; Restore saved registers
pop esi
pop ebx
mov esp, ebp ; Destroy stack frame
pop ebp
ret
测试目录的目录结构如下:
bar [directory]
bas.c
test1.c
test2.c
test3.c
foo.txt
test
在没有递归的情况下,它会按应有的方式打印测试目录中的文件,但在递归的情况下,它似乎会打印以下内容:
test1.c
bar
test3.c
[repeat 3 lines ~1000 times]
test
foo.txt
test2.c
[repeat 3 lines ~1000 times]
编辑:我认为这现在大部分是有效的,除了一开始它似乎跳回“test”下面的目录,导致它列出那里的文件和“test”中的文件两次
[SECTION .data]
ParentDir db '..', 0
CurrentDir db '.', 0
DirName db 'test', 0
[SECTION .bss]
[SECTION .text]
extern puts ; Externals from glibc standard C library
extern opendir ; Externals from dirent.h
extern closedir
extern readdir
extern chdir
global main
scandir:
pushad ; Save caller's registers
push eax ; Directory is passed in eax
call opendir ; Open directory
add esp, 4
cmp eax, 0 ; opendir returns 0 on failure
je .done
mov ebx, eax ; Move directory handle to ebx
.read:
push ebx ; Push directory handle
call readdir ; Read a file from directory
add esp, 4 ; Clean up the stack
cmp eax, 0 ; readdir returns 0 on failure or when done
je .close
add eax, 11 ; File name is offset at 11 bytes
mov cl, byte [eax] ; Get first char of filename
cmp cl, 46 ; Ignore files and dirs which begin with a dot
je .read ; (., .., and hidden files)
cmp byte [eax-1], 4
jne .notdir
push eax
call chdir
add esp, 4
mov eax, CurrentDir
call scandir ; Call scandir recursively
jmp .read
.notdir:
push eax
call puts
add esp, 4
jmp .read
.close:
push ebx ; Close directory
call closedir
add esp, 4
push ParentDir
call chdir
add esp, 4
jmp .done
.done:
popad ; Restore caller's registers
ret
main:
push ebp ; Set up stack frame for debugger
mov ebp, esp
push ebx ; Must preserve ebp, ebx, esi and edi
push esi
push edi
; start
mov eax, DirName
call scandir
; end
pop edi ; Restore saved registers
pop esi
pop ebx
mov esp, ebp ; Destroy stack frame
pop ebp
ret
你的代码看起来很好。问题在于readdir返回的路径名,您希望将其用于下一个递归步骤。返回的路径名与当前工作目录不相关 当test/目录包含一个名为test的文件时,您会看到大量的输出。当循环看到该文件名时,您将把它传递给opendir,这意味着您只需再次重新打开同一测试/目录,从而导致无限递归,直到文件句柄用完为止 解决这个问题的一种方法是在成功的opendir之后调用chdir,并在closedir之后将chdir返回到父目录,这样工作目录将始终指向您当前正在检查的目录 另外,我想用一种方法来测试文件是否为目录 返回的dirent结构在偏移量10处有一个d_类型成员,您可以检查:
...
call readdir
...
cmp byte [eax+10], 4 ; DT_DIR = 4
jne is_not_directory
你的代码看起来很好。问题在于readdir返回的路径名,您希望将其用于下一个递归步骤。返回的路径名与当前工作目录不相关 当test/目录包含一个名为test的文件时,您会看到大量的输出。当循环看到该文件名时,您将把它传递给opendir,这意味着您只需再次重新打开同一测试/目录,从而导致无限递归,直到文件句柄用完为止 解决这个问题的一种方法是在成功的opendir之后调用chdir,并在closedir之后将chdir返回到父目录,这样工作目录将始终指向您当前正在检查的目录 另外,我想用一种方法来测试文件是否为目录 返回的dirent结构在偏移量10处有一个d_类型成员,您可以检查:
...
call readdir
...
cmp byte [eax+10], 4 ; DT_DIR = 4
jne is_not_directory
谢谢我想我现在大部分时间都在工作,但它仍然给我带来一些麻烦。请参阅上面我文章中的编辑。仍然存在相同的问题-您首先列出test/目录,然后将这些路径视为相对于当前工作目录的路径,而它们不是。main中的一个快速修复方法是先将chdir转换为DirName,然后在调用scandirAh之前再转换为mov eax、CurrentDir!或者我只是将chdir部分移到scandir的开头。谢谢你的帮助,现在可以用了,谢谢。我想我现在大部分时间都在工作,但它仍然给我带来一些麻烦。请参阅上面我文章中的编辑。仍然存在相同的问题-您首先列出test/目录,然后将这些路径视为相对于当前工作目录的路径,而它们不是。main中的一个快速修复方法是先将chdir转换为DirName,然后在调用scandirAh之前再转换为mov eax、CurrentDir!或者我只是将chdir部分移到scandir的开头。谢谢你的帮助,它正在工作