简体   繁体   English

提取文件名的第一个(和最后一个)部分并将其复制到新目录

[英]Extract first (and last) part of file name and copy them to new directory

I am trying to write a Windows batch script to extract the first and last parts of a filename. 我正在尝试编写Windows批处理脚本以提取文件名的第一部分和最后一部分。

I have multiple files named like this: 我有多个这样命名的文件:

"John Doe_RandomWalk_4202.m" “ John Doe_RandomWalk_4202.m”

"Tim Meyer_plot_3c_4163.pdf" “蒂姆·迈耶_plot_3c_4163.pdf”

I would like to make directories like so: 我想制作这样的目录:

Directory "John Doe" contains "RandomWalk.m" 目录“ John Doe”包含“ RandomWalk.m”
Directory "Time Meyer" contains "plot_3c.pdf" 目录“ Time Meyer”包含“ plot_3c.pdf”

They seem to follow this pattern: "FirstName LastName_filename_[number].extension" 他们似乎遵循以下模式:“ FirstName LastName_filename_ [number] .extension”

I'm not too competed with regex. 我不太喜欢正则表达式。 I'm trying to do this with a windows batch script, however I am open to solutions in another language like Python etc. 我正在尝试使用Windows批处理脚本来执行此操作,但是我愿意接受其他语言(例如Python等)的解决方案。

Here is what I came up with: Sorry for not including my attempt earlier. 这是我想到的:很抱歉不包括我之前的尝试。 Here is what I came up with, its rather messy: 这是我想出的,很混乱:

   import os,re

   reg_exp = re.compile('_\d\d')

   filename = "John Doe_RandomWalk_4202.m" ;

   extension = filename.split('.')[-1];

   directory_name = filename.split('_')[0];

   desired_filename = filename.split('_')[1];

   final_filename = desired_filename + '.' + extension

Thanks 谢谢

If neither firstname nor lastname can contain an underscore, then you don't need regular expressions. 如果firstnamelastname都不能包含下划线,则您不需要正则表达式。

#!/usr/bin/python

import collections, os, shutil

directory_structure = collections.defaultdict(list)

for orig_filename in list_of_your_files:
    name, *filename, extension = orig_filename.split("_")
    extension = "." + extension.split(".")[-1]
    filename = '_'.join(filename) + extension
    directory_structure[name].append((filename,orig_filename))

for directory, filenames in directory_structure.items():
    try:
        os.mkdir(directory)
    except OSError:
        pass # directory already exists
    for filename in filenames:
        newfile, oldfile = filename
        shutil.copyfile(oldfile, os.path.join(directory,newfile))

If you're doing this using absolute paths, this becomes a little more difficult because you'll have to use os.path to strip off the filename from the rest of the path, then join it back together for the shutil.copyfile , but I don't see anything about absolute paths in your question. 如果使用绝对路径执行此操作,则将变得有些困难,因为您必须使用os.path从路径的其余部分剥离文件名,然后将其重新结合在一起以获取shutil.copyfile ,但是在您的问题中,我没有看到有关绝对路径的任何信息。

Since you were originally hoping for a batch implementation and I'm terrible at Python... 由于您最初希望进行批处理实现,而我对Python感到很糟糕...

@echo off
setlocal enabledelayedexpansion

set "source_dir=C:\path\to\where\your\files\are"
set "target_dir=C:\path\to\where\your\files\will\be"

:: Get a list of all files in the source directory
for /F "tokens=1,* delims=_" %%A in ('dir /b "%source_dir%"') do (
    set "folder_name=%%A"
    set name_part=%%~nB
    set file_ext=%%~xB

    REM Make a new directory based on the name if it does not exist
    if not exist "!target_dir!\!folder_name!" mkdir "!target_dir!\!folder_name!"

    REM Drop the last token from the name_part and store the new value in the new_filename variable
    call :dropLastToken !name_part! new_filename

    REM If you want to move instead of copy, change "copy" to "move"
    copy "!source_dir!\!folder_name!_!name_part!!file_ext!" "!target_dir!\!folder_name!\!new_filename!!file_ext!"
)

:: End the script so that the function doesn't get called at the very end with no parameters
exit /b

:dropLastToken
setlocal enabledelayedexpansion
set f_name=%1

:: Replace underscores with spaces for later splitting
set f_name=!f_name:_= !

:: Get the last token
for %%D in (!f_name!) do set last_token=%%D

:: Remove the last_token substring from new_filename
set f_name=!f_name: %last_token%=!

:: Put the underscores back
set f_name=!f_name: =_!

endlocal&set %2=%f_name%

Since we don't know the structure of the filenames beforehand, a regex might suit you better. 由于我们事先不知道文件名的结构,因此正则表达式可能更适合您。 Here's an implementation in Python: 这是Python中的实现:

import os
import re

# Grab everything in this directory that is a file

files = [x for x in os.listdir(".") if os.path.isfile(x)]

# A dictionary of name: filename pairs.
output = {}

for f in files:

    """
    Match against the parts we need:

    ^ --> starts with
    ([a-zA-Z]+) --> one or more alphanumeric characters 
                        or underscores (group 1)
    \s+ --> followed by one or more spaces
    ([a-zA-Z]+)_ --> Another alphanumeric block, followed
                                by an underscore (group 2)
    (\w+) --> A block of alphanumeric characters or underscores (group 3)
    _\d+\. --> Underscore, one or more digits, and a period
    (.+) --> One or more characters (not EOL) (group 4)
    $ --> End of string

    """
    m = re.match("^([a-zA-Z]+)\s+([a-zA-Z]+)_(\w+)_\d+\.(.+)$", f)
    if m:
        # If we match, grab the parts we need and stuff it in our dict
        name = m.group(1) + " " + m.group(2)
        filename = m.group(3) + "." + m.group(4)

        output[name] = filename

for name in output:
    print 'Directory "{}" contains "{}"'.format(name, output[name])

Note that this isn't optimally compact, but is relatively easy to read. 请注意,这并不是最佳的紧凑形式,但是相对易于阅读。 You should also be able to do: 您还应该能够:

import os
import re

output = {name: filename for (name, filename) in [
    (m.group(1) + " " + m.group(2), m.group(3) + "." + m.group(4))
        for m in [
            re.match("^(\w+)\s+([a-zA-Z]+)_(\w+)_\d+\.(.+)$", f)
                for f in os.listdir(".") if os.path.isfile(f)
                ]
        if m
    ]
}

With my limited python experience I came up with this. 以我有限的python经验,我想到了这一点。 It works, though probably not the best way: 它可以工作,尽管可能不是最好的方法:

import collections, os, shutil

list_of_your_files = [f for f in os.listdir('.') if os.path.isfile(f)];

for filename in list_of_your_files:

    extension = filename.split('.')[-1];

    directory = filename.split('_')[0];

    desired_filename = filename.split('_')[1];

    final_filename = desired_filename + '.' + extension

    try:
        os.mkdir(directory)
    except OSError:
        pass # directory already exists

    ##newfile, oldfile = final_filename
    shutil.copyfile(filename, os.path.join(directory,final_filename))

暂无
暂无

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

相关问题 如何提取文件名的第一部分? - How to extract first part of a file name? 使用非静态文件名的一部分来创建新目录 - Use part of non static file name to create new directory Python 将文件复制到新目录并在文件名已存在时重命名 - Python copy files to a new directory and rename if file name already exists 复制到新目录后更改文件名[已解决] - Change Name of file after copy to new directory [SOLVED] 删除句点,然后将“@”后的 email 扩展名删除到新列中以提取名字和姓氏信息 - Remove period then email extension after '@' into new column to extract first and last name information 将文件复制并重命名到新目录 - Copy and Rename file to new directory 试图从一个目录中的许多文本文件中复制一组特定的字符串并将它们粘贴到一个新的文本文件中 - Trying to copy a set of specific strings from many text files in a directory and paste them in a new text file Python提取文件名regex的一部分 - Python extract part of file name regex 如何在包含全名的列表中提取名称(名字)的第一部分并丢弃一部分名称 - how to extract first part of name(first name) in a list that contains full names and discard names with one part Python:如何获取多个.csv文件的列的第一个值及其名称,并使用它们创建一个新文件 - Python: How to take the first value of a column of multiple .csv files + its name and make a new file with them
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM