[英]Changing name of the file to parent folder name
我的目录中有一堆文件夹。 他们每个人都有一个文件,您可以在下面看到:
不管文件扩展名是什么,我都希望这个文件的名称与其父文件夹完全相同,即在考虑文件夹 2023-10-18 时,我希望文件位于2023-10-18而不是掩星。 ...
我尝试使用此线程重命名多个文件:
和这里
但不幸的是,在应用了这样的代码之后:
import os
from pathlib import Path
pth = Path(__file__).parent.absolute()
files = os.listdir(pth)
for file in files:
os.rename(os.pth.join(pth, file), os.pth.join(pth, '' + file + '.kml'))
我有一个错误:
AttributeError: 模块 'os' 没有属性 'pth'
此处描述:
AttributeError: 'module' object 没有属性
这对我来说只是一点点,因为我是 Python 的新手。
如何自动更改这些目录中所有文件的名称? 我需要与目录名相同的文件名。 是否可以?
更新:
在下面提示之后,我的代码现在看起来像这样:
import os
from pathlib import Path
pth = Path(__file__).parent.absolute()
files = os.listdir(pth)
for file in files:
os.rename(os.path.join(pth, file), os.path.join(pth, '' + file + '.kml'))
但不是更改文件夹列表中的文件名,而是将给定目录中的所有文件更改为 .kml。 如何访问文件夹列表中的各个文件?
因此,根据我的理解,每个文件夹中都有一个文件。 您想要使用相同的文件夹名称重命名文件并保留扩展名。
import os
# Passing the path to your parent folders
path = r'D:\bat4'
# Getting a list of folders with date names
folders = os.listdir(path)
for folder in folders:
files = os.listdir(r'{}\{}'.format(path, folder))
# Accessing files inside each folder
for file in files:
# Getting the file extension
extension_pos = file.rfind(".")
extension = file[extension_pos:]
# Renaming your file
os.rename(r'{}\{}\{}'.format(path, folder, file),
r'{}\{}\{}{}'.format(path, folder, folder, extension))
我在我自己的文件上试过如下:
这是 output 的示例:
我希望我明白你的意思。 :)
这是一个仅使用os
和shutil
模块的简单解决方案,它们都已预安装。 它是跨平台的,对我来说工作得很好而且很快。 它还可以处理每个子文件夹中的多个文件。
我认为您可以从评论中理解代码,但如果不是这样,请随时通知我。
import os, shutil
from os.path import * # just to avoid typing "os.path." everywhere
# I am using abspath() here to get the absolute path to the folder.
folder = abspath(input('Enter the main folder: '))
# index through all elements in the main folder that are directories
for subfolder in os.listdir(folder):
abs_subfolder = join(folder, subfolder) # get the folder's absolute path
if not isdir(abs_subfolder):
continue # go to the next element because this one wasn't a folder
# index through all the files in this subfolder
for file in os.listdir(abs_subfolder):
# get the extension of the file to move
extension = splitext(file)[1]
new_file_path = abs_subfolder + '.' + extension
# move the file to its parent directory, and change its name
shutil.move(join(abs_subfolder, file), new_file_path)
# delete the directory the files were in
# you can comment the next line if you don't want that to happen
os.rmdir(abs_subfolder)
基本上,这段代码所做的是对包含所有这些子文件夹及其中的文件的文件夹内的每个目录进行索引。
然后,它搜索每个子文件夹中的每个文件,然后将这些文件移动到主文件夹,同时将它们的名称更改为它们所在的子文件夹。
最后,一旦该子文件夹的每个文件都被移动并重命名,它就会删除空目录。 如果您不希望这种情况发生,您可以只评论最后一行。
我希望这有帮助。
另外,我不知道你的代码是从哪里来的,但你到处都是.kml
的原因是因为代码所做的就是将所有文件夹重命名为它们的名称 + .kml
。 它甚至不涉及子文件夹中的文件。 我不认为我可以让你的代码按你想要的方式工作而不改变其中的几乎所有内容。
如果您想了解有关os
模块的更多信息,请查看此页面以及os.path
的这一页面。 我会说shutil
只是os
模块的“补充”,它与 is 有一些相似之处,但您可以在此处查看完整文档。
如果你想总体上学习 Python,我认为w3schools是 go 的最佳去处。
每行代码推理都有注释! 每个答案都应该使用iglob
,请在此处阅读更多相关信息! 该代码也是后缀不可知的( .klm
因为后缀不是硬编码的),并且适用于需要此实用程序的任何场景。
只使用了标准的库函数。
import os
from shutil import move
from glob import iglob
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
# The .py file has to be on the same directory as the folders containing the files!
root = Path(__file__).parent
# Using threading in case the operation becomes I/O bound (many files)
with ThreadPoolExecutor() as executor:
for file in iglob(str(root / "**" / "*")):
file = Path(file)
# The new filename is the name of the directory, and the suffix(es) of the original file
new_filename = f"{file.parent.name}{''.join(file.suffixes)}"
# Move AND rename simultaneosly
executor.submit(move, file, root / new_filename)
# Delete directory because it is empty, and has no utility; ommit this line if not True
executor.submit(os.rmdir, file.parent)
如果您真的只想重命名文件,并将它们保存在各自的目录中:
import os
from shutil import move
from glob import iglob
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
RENAME_ONLY = True
# The .py file has to be on the same directory as the folders containing the files!
root = Path(__file__).parent
# Using threading in case the operation becomes I/O bound
with ThreadPoolExecutor() as executor:
for file in iglob(str(root / "**" / "*")):
file = Path(file)
# The new filename is the name of the directory, and the suffix(es) of the original file
new_filename = f"{file.parent.name}{''.join(file.suffixes)}"
if RENAME_ONLY:
executor.submit(os.rename, file, file.parent / new_filename)
else:
# Move AND rename simultaneosly
executor.submit(move, file, root / new_filename)
# Delete directory because it is empty, and has no utility; ommit this line if not True
executor.submit(os.rmdir, file.parent)
''.join(file.suffixes)
? 有些文件有多个句点; 像abc.x.yz
。 我们得到带有.yz
的file.suffix
和.x.yz
''.join(file.suffixes)
; 因此我选择使用后者。
这是对子后缀的敏感性问题,这通常很重要。 例如, .tar.gz
文件file.suffix
不会捕获.tar
,这对文件格式有害。
您需要将它保存到一个文件(例如,rename.py)并使用 python 解释器和一个附加参数调用它 - 您要为其子目录中的文件重命名的父目录的名称。 例如:“python rename.py parent_dir”。 目录名可以是绝对的或相对的。 作为附加参数,您还可以在重命名文件时指定用于保存扩展名的密钥(0 - 不保存,1 - 保存)。 默认情况下不保存扩展名。 这是保存扩展名的示例:“python rename.py parent_dir 1”。
rename.py 中的脚本:
import os
import sys
def rename_first_file_in_dir(dir_path, new_file_name, keep_extension = False):
for current_file_name in os.listdir(dir_path):
current_file_path = os.path.join(dir_path, current_file_name) # full or relative path to the file in dir
if not os.path.isfile(current_file_path):
break
# rename only base name of file to the name of directory
if keep_extension:
file_extension = os.path.splitext(current_file_name)[1]
if len(file_extension) > 0:
new_file_name = new_file_name + file_extension
new_file_path = os.path.join(dir_path, new_file_name)
print("File " + current_file_name + " renamed to " + new_file_name + " in " + os.path.basename(dir_path) + " directory");
os.rename(current_file_path, new_file_path)
# exit after first processed file
break
if len(sys.argv) < 2:
print("Usage: python " + os.path.basename(__file__) + " <directory> [keep_files_extensions]") # help for usage
exit(0)
scan_dir = sys.argv[1]
keep_extension = False if len(sys.argv) < 3 else not (int(sys.argv[2]) == 0) # optional parameter 0 - False, 1 - True, by default - False
if not os.path.exists(scan_dir):
print("Error: directory " + scan_dir + " does not exists")
exit(-1)
if not os.path.isdir(scan_dir):
print("Error: file " + scan_dir + " is not a directory")
exit(-1)
print("Scanning directory " + scan_dir)
for file_name in os.listdir(scan_dir): # walk through directory
file_path = os.path.join(scan_dir, file_name)
if os.path.isdir(file_path):
rename_first_file_in_dir(file_path, file_name, keep_extension)
这里有一个使用 pathlib 模块的示例代码。 请务必修改 base_folder。
解决方案 1
"""
rename_filename.py
Rename filename inside the folders.
https://stackoverflow.com/questions/71408697/changing-name-of-the-file-to-parent-folder-name
Example:
base_folder
F:/Tmp/s13/
sub_folders
F:/Tmp/s13/2022-05-01
F:/Tmp/s13/2022-08-01
files under subfolder
F:/Tmp/s13/2022-05-01/aa.txt
F:/Tmp/s13/2022-08-01/bb.txt
Usage:
Be sure to modify first the "base_folder" value in the main()
command lines:
python rename_filename.py or
python3 rename_filename.py
"""
from pathlib import Path # python version >= 3.4
def rename_file(base_folder):
"""
Rename the filename of the file under the sub-folders of the base_folder.
"""
base_path = Path(base_folder).glob('*/*')
# Get the file path in every sub-folder.
for file in base_path:
# print(file)
sub_folder_abs_path = file.parent # sub-folder path, F:/Tmp/s13/2022-05-01
sub_folder_name = file.parent.name # sub-folder name, 2022-05-01
# Rename the file to sub-folder name.
new_file = Path(sub_folder_abs_path, sub_folder_name)
file.rename(new_file)
def main():
# Change the base folder according to your case.
base_folder = 'F:/Tmp/s13/'
rename_file(base_folder)
if __name__ == '__main__':
main()
方案二
使用 pathlib 和 argparse 模块。 它提供 --base-folder 选项来定位基本文件夹,无需修改源。 见用法。
"""
rename_file.py
Rename filename inside the folders.
https://stackoverflow.com/questions/71408697/changing-name-of-the-file-to-parent-folder-name
Example:
base_folder
F:/Tmp/s13/
sub_folders
F:/Tmp/s13/2022-05-01
F:/Tmp/s13/2022-08-01
files under subfolder
F:/Tmp/s13/2022-05-01/aa.txt
F:/Tmp/s13/2022-08-01/bb.txt
Usage:
command line:
python rename_file.py --base-folder "F:/Tmp/s13/"
"""
from pathlib import Path # python version >= 3.4
import argparse
def rename_file(base_folder):
"""
Rename the filename of the file under the sub-folders of the base_folder.
"""
base_path = Path(base_folder).glob('*/*')
# Get the file path in every sub-folder.
for file in base_path:
# print(file)
sub_folder_abs_path = file.parent # sub-folder path, F:/Tmp/s13/2022-05-01
sub_folder_name = file.parent.name # sub-folder name, 2022-05-01
# Rename the file to sub-folder name.
new_file = Path(sub_folder_abs_path, sub_folder_name)
file.rename(new_file)
def main():
parser = argparse.ArgumentParser(description='Rename file to sub-folder name.')
parser.add_argument('--base-folder', required=True,
help='the base folder, example: --base-folder "f:/tmp/so13/"')
args = parser.parse_args()
rename_file(args.base_folder)
if __name__ == '__main__':
main()
用法:
打开命令提示符和 CD 到 rename_file.py 的位置。
python rename_file.py --base-folder "f:/tmp/s13/"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.