我正在尝试编写Windows批处理脚本来提取文件名的第一部分和最后部分。
我有多个文件名如下:
" John Doe_RandomWalk_4202.m"
" Tim Meyer_plot_3c_4163.pdf"
我想制作这样的目录:
目录" John Doe"包含" RandomWalk.m"
目录"时间迈耶"包含" 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
由于
答案 0 :(得分:1)
如果firstname
和lastname
都不能包含下划线,那么您就不需要正则表达式。
#!/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
,但我在你的问题中没有看到关于绝对路径的任何信息。
答案 1 :(得分:1)
因为你最初希望批处理实现,而且我在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%
答案 2 :(得分:1)
由于我们事先并不知道文件名的结构,因此正则表达式可能更适合您。这是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
]
}
答案 3 :(得分:-1)
凭借我有限的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))