![](/img/trans.png)
[英]rsync recursively and exclude content of specific directory, not the directory
[英]Recursively list directory content, plus check if file is directory
我正在嘗試學習匯編,所以如果我的問題很簡單,請多包涵
以下代碼掃描目錄並打印出其中的所有文件和目錄,但以點開頭的文件和目錄除外。 似乎工作正常。
但是,一旦取消注釋call scandir
行以打開遞歸,它就會打印出一長串重復的文件名(有關詳細信息,請參見下文)。
另外,我想一種方法來測試文件是否是目錄。 我該怎么做? 據我所知這不是問題,目前,因為如果它不是目錄,則對scandir的調用將不做任何事情而返回,但是此后的檢查可能變得很重要(這似乎是一件好事無論如何)。
[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]
編輯:我認為,這現在大多數情況下都有效,除了它似乎最初會跳回到“測試”下面的目錄中,導致它兩次列出該文件和“測試”中的文件
[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
,這意味着您只需再次重新打開相同的test/
目錄,就可以進行無限遞歸,直到用完文件句柄為止。
解決方法之一就是打電話chdir
成功后opendir
(也chdir
后回父目錄closedir
),這樣的工作目錄將始終指向您當前正在檢查一個。
另外,我想一種方法來測試文件是否是目錄。
readdir返回的dirent
結構具有一個d_type
成員(偏移量為10),您可以檢查該成員:
...
call readdir
...
cmp byte [eax+10], 4 ; DT_DIR = 4
jne is_not_directory
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.