簡體   English   中英

提取文件名的第一個(和最后一個)部分並將其復制到新目錄

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

我正在嘗試編寫Windows批處理腳本以提取文件名的第一部分和最后一部分。

我有多個這樣命名的文件:

“ John Doe_RandomWalk_4202.m”

“蒂姆·邁耶_plot_3c_4163.pdf”

我想制作這樣的目錄:

目錄“ John Doe”包含“ RandomWalk.m”
目錄“ Time Meyer”包含“ plot_3c.pdf”

他們似乎遵循以下模式:“ FirstName LastName_filename_ [number] .extension”

我不太喜歡正則表達式。 我正在嘗試使用Windows批處理腳本來執行此操作,但是我願意接受其他語言(例如Python等)的解決方案。

這是我想到的:很抱歉不包括我之前的嘗試。 這是我想出的,很混亂:

   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

謝謝

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

如果使用絕對路徑執行此操作,則將變得有些困難,因為您必須使用os.path從路徑的其余部分剝離文件名,然后將其重新結合在一起以獲取shutil.copyfile ,但是在您的問題中,我沒有看到有關絕對路徑的任何信息。

由於您最初希望進行批處理實現,而我對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%

由於我們事先不知道文件名的結構,因此正則表達式可能更適合您。 這是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])

請注意,這並不是最佳的緊湊形式,但是相對易於閱讀。 您還應該能夠:

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
    ]
}

以我有限的python經驗,我想到了這一點。 它可以工作,盡管可能不是最好的方法:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM