- 1. os.walk(遍历多层文件夹)
- 1.1 一般用法
- 1.2 访问特定层级/深度的文件夹
- 1.3 排除os.walk中部分文件夹的迭代
- 1.4 统计多层文件结构的文件/文件夹数量
- 2. os.listdir
- 3. pathlib.Path.glob
- 4. 判断一个文件是普通文件还是文件夹
- 5. 重命名,移动/复制文件
- 5.1 os.rename
- 5.2 shutil.move
- 5.3 shutil.copy
我现在有以下文件夹结构,为了处理.dcm文件,需要在LCTSC-Test-S1-101文件的基础上,访问到存储.dcm文件所在的文件夹。
~/Downloads/LCTSC/LCTSC-Test-S1-101 » tree -L 3
.
└── 03-03-2004-NA-NA-08186
├── 1.000000-NA-56597
│ └── 1-1.dcm
└── NA-79262
├── 1-001.dcm
├── 1-002.dcm
因此考虑使用os.walk,示例如下:
for root, dirs, files in os.walk(nii_name_path[0], topdown=True):
for name in files[:3]: # 打印文件
print(os.path.join(root, name))
for name in dirs: # 打印所有目录/文件夹
print(os.path.join(root, name))
# 结果如下
> ../LCTSC/LCTSC-Train-S2-008/01-09-1999-NA-4DCT THORAX-15057
../LCTSC/LCTSC-Train-S2-008/01-09-1999-NA-4DCT THORAX-15057/1.000000-.simplified-23857
../LCTSC/LCTSC-Train-S2-008/01-09-1999-NA-4DCT THORAX-15057/211.000000-Ave-IP10 0102030405060708090-83140
../LCTSC/LCTSC-Train-S2-008/01-09-1999-NA-4DCT THORAX-15057/1.000000-.simplified-23857/1-1.dcm
../LCTSC/LCTSC-Train-S2-008/01-09-1999-NA-4DCT THORAX-15057/211.000000-Ave-IP10 0102030405060708090-83140/21-008.dcm
../LCTSC/LCTSC-Train-S2-008/01-09-1999-NA-4DCT THORAX-15057/211.000000-Ave-IP10 0102030405060708090-83140/13-002.dcm
../LCTSC/LCTSC-Train-S2-008/01-09-1999-NA-4DCT THORAX-15057/211.000000-Ave-IP10 0102030405060708090-83140/03-002.dcm
参考:
- 菜鸟教程:Python os.walk() 方法
- GeeksforGeeks:os.walk() in Python
- Stack Overflow:A Faster way of Directory walking instead of os.listdir?,这个问题是讨论os.walk等的运行效率的
根据参考内容进行整理,没有特别高档的方法,都是walk的结果进行一些简单的判断,让它不至于输出。
解决1
来自Github wiki:A python function to do an os.walk(), but only to a certain depth. A negative depth indicates full depth.
import os
def walklevel(path, depth = 1):
"""It works just like os.walk, but you can pass it a level parameter
that indicates how deep the recursion will go.
If depth is 1, the current directory is listed.
If depth is 0, nothing is returned.
If depth is -1 (or less than 0), the full depth is walked.
"""
if depth < 0:
for root, dirs, files in os.walk(path):
yield root, dirs[:], files
return
elif depth == 0:
return
base_depth = path.rstrip(os.path.sep).count(os.path.sep)
for root, dirs, files in os.walk(path):
yield root, dirs[:], files
cur_depth = root.count(os.path.sep)
if base_depth + depth <= cur_depth:
del dirs[:]
解决2
来自Stack Overflow:os.walk without digging into directories below
import os
def walklevel(some_dir, level=1):
some_dir = some_dir.rstrip(os.path.sep)
assert os.path.isdir(some_dir)
num_sep = some_dir.count(os.path.sep)
for root, dirs, files in os.walk(some_dir):
yield root, dirs, files
num_sep_this = root.count(os.path.sep)
if num_sep + level <= num_sep_this:
del dirs[:]
参考:
- python os.walk to certain level
参考Stack Overflow:Excluding directories in os.walk
只需要加一个判断即可,例如:
exclude = set(['New folder', 'Windows', 'Desktop'])
for root, dirs, files in os.walk(top, topdown=True):
dirs[:] = [d for d in dirs if d not in exclude]
1.4 统计多层文件结构的文件/文件夹数量
import os
base_dir="XXX"
all_files=[]
all_dir=[]
for root, dirs, files in os.walk(base_dir, topdown=True):
for name in dirs:
all_dir.append(os.path.join(root, name))
for name in files:
if "DS_Store" not in name: # 如果是mac,排除.DS_Store文件问题
all_files.append(os.path.join(root, name))
print(len(all_dir))
print(len(all_files))
2. os.listdir
import os base_dir="XXX" file_list=os.listdir(base_dir)3. pathlib.Path.glob
根据Stack Overflow:How to use glob() to find files recursively?
例如,我想找到一个文件夹中所有以LCTSC开头的文件夹,文件结构如下:
~/Downloads/LCTSC » tree -L 1 . ├── LCTSC-Test-S1-101 ├── LCTSC-Test-S1-102 ├── LCTSC-Test-S1-103 ├── LCTSC-Test-S1-104 ├── LCTSC-Test-S1-201 ├── LCTSC-Test-S1-202 ├── ... └── LICENSE
可以:
import glob
nii_name_path=glob.glob('../LCTSC/LCTSC*')
glob函数不像listdir一样,有一个单独的路径参数,它只接受一个参数,在指定base_dir的同时就要写好筛选文件的正则表达式,如上。
参考:
- CSDN博客:python os.path glob.glob函数
- python官方文档:glob — Unix style pathname pattern expansion
- os.path.exists(path),判断这个路径是否正确,这个路径可以是一个文件夹/文件或者软连接(快捷方式)等
- os.path.isfile(path),如果路径是一个普通文件或者指向一个文件的链接,则返回true
- os.path.isdir(path),如果路径是一个文件夹或者指向文件夹的链接,则返回true
例如:
import os.path
if os.path.isfile('filename.txt'):
print ("File exist")
else:
print ("File not exist")
参考:
- How to Check if a File or Directory Exists in Python
示例
os.rename("../a/123.txt","../b/12.txt")
语法
将src参数所代表的文件或者目录重命名为dst,如果dst已经存在,会抛出一个OSError子类的错误,执行失败。
- 在Windows平台上,如果dst存在,则总是会抛出FileExistsError
- 在Unix上,
- 如果scr是一个文件,dst是一个目录(反之也可以),则会分别抛出一个IsADirectoryError或NotADirectoryError错误。
- 如果两个都是目录,dst为空,则dst会被静默替换;如果dst一个非空的目录,则会抛出OSError错误.
- 如果两个都是文件,如果用户具有权限,则dst将会被静默替换。如果 src 和 dst 在不同的文件系统上,该操作可能会在某些 Unix上失败。 如果成功,重命名将是一个原子操作(这是 POSIX 要求)。
- 此函数可以支持指定 src_dir_fd 和 dst_dir_fd 以提供相对于目录描述符的路径。
文件夹内操作相当于直接重命名,跨文件夹操作相当于移动文件并重命名(没有复制,直接移动)
参考:
- 菜鸟教程:Python os.rename() 方法
- python官方文档:os.rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None)
- 博客园文章:【原创】Python rename用法
示例
import shutil
shutil.move('file.txt', 'path/to/new/directory/')
语法解释
shutil.move(src, dst, copy_function=copy2)
- 迭代的将一个文件或者目录(scr参数)移动到另一个地址(dst参数),返回dst
- 如果dst是一个已有的目录,则src会直接移动到这个目录中。
- 如果dst已经存在但不是一个目录,其会根据os.rename()的语法来决定是否覆盖
- 如果dst位于当前的文件系统中,则直接使用os.rename()(即src和dst在同一目录中)。
- 否则在其他情况时,src会使用copy_function复制到dst,然后被删除。
- 如果是软链接,则会有一个指向src代表的目标的新链接被创建,同时scr会被删除
- copy_function是一个可以自己指定函数的参数,一般不使用
shutil.move与os.rename的区别
- 从调用上就可以看出明显的区别。
os.rename("../a/123.txt","../b/12.txt") shutil.move('file.txt', 'path/to/new/directory/') - shutil.move的第二个参数只能是个目录
- os.rename可以在重命名的时候捎带就移动个位置
参考:
- Stack Overflow:Rename and move file with Python
- os.rename vs shutil.move
- python官方文档:shutil.move(src, dst, copy_function=copy2)
shutil.copy(src, dst, *, follow_symlinks=True)
示例
import shutil
shutil.copy(oldName, newName)
os.rename("../a/123.txt","../b/12.txt")
shutil.copy("../a/123.txt","../b/12.txt")
"""
二者的区别在于,
rename是移动,src中的文件会消失
而copy是复制,scr中的文件依然会保留
"""
参考
- python官方文档:shutil.copy(src, dst, *, follow_symlinks=True)
- python 复制一个文件并进行重命名



