简体   繁体   English

将文件名称更改为父文件夹名称

[英]Changing name of the file to parent folder name

I have a bunch of folders in my directory.我的目录中有一堆文件夹。 In each of them there is a file, which you can see below:他们每个人都有一个文件,您可以在下面看到:

在此处输入图像描述

Regardless the file extension I would like to have the name of this file to be exactly the same as its parent folder, ie when considering folder 2023-10-18 I would like to have the file inside 2023-10-18 instead of occultation....不管文件扩展名是什么,我都希望这个文件的名称与其父文件夹完全相同,即在考虑文件夹 2023-10-18 时,我希望文件位于2023-10-18而不是掩星。 ...

I tried to rename the multiple files by using this thread:我尝试使用此线程重命名多个文件:

Renaming multiple files in a directory using Python 使用 Python 重命名目录中的多个文件

and here和这里

https://pynative.com/python-rename-file/#:~:text=Use%20rename()%20method%20of,function%20to%20rename%20a%20file . https://pynative.com/python-rename-file/#:~:text=Use%20rename()%20method%20of,function%20to%20rename%20a%20file

but unfortunately after application the code like this:但不幸的是,在应用了这样的代码之后:

 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'))

I have an error:我有一个错误:

AttributeError: module 'os' has no attribute 'pth' AttributeError: 模块 'os' 没有属性 'pth'

described here:此处描述:

AttributeError: 'module' object has no attribute AttributeError: 'module' object 没有属性

which says only a little to me, as I am a novice in Python.这对我来说只是一点点,因为我是 Python 的新手。

How can I auto change the name of all the files in these directories?如何自动更改这些目录中所有文件的名称? I need the same filename as the directory name.我需要与目录名相同的文件名。 Is it possible?是否可以?

UPDATE:更新:

After hint below, my code looks like this now:在下面提示之后,我的代码现在看起来像这样:

 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'))

but instead of changing the filename inside the folder list, all the files in the given directory have been changed to.kml.但不是更改文件夹列表中的文件名,而是将给定目录中的所有文件更改为 .kml。 How can I access to the individual files inside the folderlist?如何访问文件夹列表中的各个文件?

在此处输入图像描述

So, based on what I understood, you have a single file in each folder.因此,根据我的理解,每个文件夹中都有一个文件。 You would like to rename the file with the same folder name and preserve the extension.您想要使用相同的文件夹名称重命名文件并保留扩展名。

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))

I have tried it on my own files as follows:我在我自己的文件上试过如下:

在此处输入图像描述

在此处输入图像描述

This is an example for the output:这是 output 的示例:

在此处输入图像描述

I hope I got your point.我希望我明白你的意思。 :) :)

Here is a simple solution using only the os and shutil modules, both already preinstalled.这是一个仅使用osshutil模块的简单解决方案,它们都已预安装。 It is cross-platform and works fine and fast for me.它是跨平台的,对我来说工作得很好而且很快。 It can also handle multiple files being in each of the subfolders.它还可以处理每个子文件夹中的多个文件。

I think you can understand the code from the comments, but feel free to notify me if that's not the case.我认为您可以从评论中理解代码,但如果不是这样,请随时通知我。

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)

Basically, what this code does is to index through every directory inside the folder that contains all of these subfolders with files inside them.基本上,这段代码所做的是对包含所有这些子文件夹及其中的文件的文件夹内的每个目录进行索引。

Then, it searches for every file in each of these subfolders, then it moves these files to the main folder while changing their name to the subfolder's that they were in.然后,它搜索每个子文件夹中的每个文件,然后将这些文件移动到主文件夹,同时将它们的名称更改为它们所在的子文件夹。

Finally, once every file of that subfolder has been moved and renamed, it removes the empty directory.最后,一旦该子文件夹的每个文件都被移动并重命名,它就会删除空目录。 You can just comment the last line if you don't want that to happen.如果您不希望这种情况发生,您可以只评论最后一行。

I hope that helps.我希望这有帮助。


Also, I don't know where you got your code from, but the reason why you are getting .kml everywhere is because all that the code does is to rename all of your folders into their name + .kml .另外,我不知道你的代码是从哪里来的,但你到处都是.kml的原因是因为代码所做的就是将所有文件夹重命名为它们的名称 + .kml It doesn't even touch the files in the subfolders.它甚至不涉及子文件夹中的文件。 I don't think I can make your code work as you want without changing pretty much everything in it.我不认为我可以让你的代码按你想要的方式工作而不改变其中的几乎所有内容。


If you want to learn more about the os module, check out this page as well as this one for os.path .如果您想了解有关os模块的更多信息,请查看此页面以及os.path这一页面。 I would say shutil is just a "complement" to the os module, and it shares some similarities with is, but you can see the full documentation here .我会说shutil只是os模块的“补充”,它与 is 有一些相似之处,但您可以在此处查看完整文档。

If you would like to learn Python in general, I think w3schools is the best place to go.如果你想总体上学习 Python,我认为w3schools是 go 的最佳去处。

Reasoning for each line of code are commented!每行代码推理都有注释! Every answer should use iglob , please read more about it here !每个答案都应该使用iglob ,请在此处阅读更多相关信息! The code is also suffix agnostic ( .klm as the suffix is not hardcoded), and works in any scenario that requires this utility.该代码也是后缀不可知的( .klm因为后缀不是硬编码的),并且适用于需要此实用程序的任何场景。

Only standard liberary functions were used.只使用了标准的库函数。

The most satisfying method: Move out of directory, rename, and delete directory最满意的方法:移出目录,重命名,删除目录

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)

Less satisfying;不太满意; OPs request: Rename file (keep inside directory) OPs请求:重命名文件(保留在目录内)

In case you really want to only rename the files, and keep them in their respective directory:如果您真的只想重命名文件,并将它们保存在各自的目录中:

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)

Why ''.join(file.suffixes) ?为什么''.join(file.suffixes)

There are files that have multiple periods;有些文件有多个句点; like abc.x.yz .abc.x.yz We get .yz with file.suffix , and .x.yz with ''.join(file.suffixes) ;我们得到带有.yzfile.suffix.x.yz ''.join(file.suffixes) hence my choice to use the latter.因此我选择使用后者。

It is a matter of sensitivity towards sub-suffixes, which are often important.这是对子后缀的敏感性问题,这通常很重要。 For instance, .tar.gz files file.suffix wouldn't catch .tar , which is detrimental to the file format.例如, .tar.gz文件file.suffix不会捕获.tar ,这对文件格式有害。

You need to save it to a file (for example, rename.py) and call it using the python interpreter with an additional parameter - the name of the parent directory for which you want to rename the files in its subdirectories.您需要将它保存到一个文件(例如,rename.py)并使用 python 解释器和一个附加参数调用它 - 您要为其子目录中的文件重命名的父目录的名称。 For example: "python rename.py parent_dir".例如:“python rename.py parent_dir”。 The directory name can be either absolute or relative.目录名可以是绝对的或相对的。 As an additional parameter, you can also specify the key for saving the extension when renaming a file (0 - do not save, 1 - save).作为附加参数,您还可以在重命名文件时指定用于保存扩展名的密钥(0 - 不保存,1 - 保存)。 Extensions are not saved by default.默认情况下不保存扩展名。 Here's an example with saving an extension: "python rename.py parent_dir 1".这是保存扩展名的示例:“python rename.py parent_dir 1”。

Script in rename.py: 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)

Here a sample code using pathlib module.这里有一个使用 pathlib 模块的示例代码。 Be sure to modify the base_folder.请务必修改 base_folder。

Solution 1解决方案 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()

Solution 2方案二
Uses pathlib and argparse modules.使用 pathlib 和 argparse 模块。 It offers --base-folder option to locate the base folder no need to modify the source.它提供 --base-folder 选项来定位基本文件夹,无需修改源。 See usage.见用法。

"""
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()

Usage:用法:
Open command prompt and CD to the location of rename_file.py.打开命令提示符和 CD 到 rename_file.py 的位置。

python rename_file.py --base-folder "f:/tmp/s13/"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM