批处理脚本根据文件名查找文件夹(LAST NAME FIRST)(最后名称第一名)

时间:2016-09-19 06:46:33

标签: batch-file

我使用的是Windows 7。

我有数百个文件需要移动到各自的文件夹中。这是一个示例文件名:

文件名:" SMITH John登录表"

遗憾的是,这些文件夹仅以其最后名称和名字命名。例如:

文件夹名称:SMITH John已完成。

我已经创建了一个批处理脚本(感谢其他Q& As),如果文件夹名称为" LAST Name和First name"但是,如果文件夹名称在名字后面有额外的单词,则需要帮助。任何建议都会很棒。

2 个答案:

答案 0 :(得分:0)

您可以使用for循环提取字符串的特定部分:

@echo off
setlocal EnableDelayedExpansion
for /f "tokens=1,2 delims= " %%a in ("!placefilenameshere!") do (
set lastname=%%a
set firstname=%%b
)

使用另一个for循环,您可以自己完成(子)目录:

set parentdir="C:\foo\bar"
REM you can use network paths as well!
pushd !parentdir!
for /r %%g in (.) do (

  set dirname=%%g
  set dirsave=%%g
  for /L %%I in (1,1,20) do set dirname=!dirname:*\=!

for /f "tokens=1,2 delims= " %%m in ("!dirname!") do (
set lastdir=%%m
set firstdir=%%n
)

  if /i "x!lastdir! !firstdir!"=="x!lastname! !firstname!" (
      popd
      REM MOVE FILES TO DIRSAVE
      pushd !parentdir!
  )
)

说明: 使用第一个块从文件名中提取前两个单词,您可以将循环的第一个括号放在变量中,例如。 因此,last-和firstname保存在两个变量lastnamefirstname中 将变量parentdir更改为您要放置文件的所有文件夹所在的路径。 第二个循环遍历上面指定的目录中的文件夹,并将目录路径保存在两个变量中。一个用于稍后datsave,一个用于检查是否找到了正确的目录datname。 那里的小循环从路径变量中删除所有父目录字符串,然后从中获取前两个单词。

实施例: C:\some\long\path\goes here首先缩短为goes here,然后分为lastdir = goesfirstdir = here

最后一步是检查目录中的前两个单词和文件名是否相同(不区分大小写)。在那里你可以放置命令将文件移动到路径dirsave,这是保存的完整路径(见上文)。

将所有内容放入另一个遍历文件名的循环中,它应该可以正常工作。

然而,这是未经测试的......有些经验丰富的人可能希望在出现问题之前首先考察一下......

答案 1 :(得分:0)

@ECHO Off
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
FOR /f "delims=" %%a IN (
 'dir /b /a-d "%sourcedir%\*" '
 ) DO (
 SET "destsubdir="
 CALL :finddest %%a
 IF DEFINED destsubdir (CALL :transfer "%%a"
 ) ELSE (
  ECHO %%a: No unique subdir found
 )
)

GOTO :EOF

:transfer
ECHO(MOVE "%sourcedir%\%~1" "%destdir%\%destsubdir%\"
GOTO :eof

:finddest
:: get the next subdir part
SET "subdirfound=%1"
:: If there are no more, exit - unique not found
IF NOT DEFINED subdirfound GOTO nouniquefound
:: see whether there is exactly one destination subdir with
:: the accumulated subdirname so far
IF DEFINED destsubdir (
 SET "accumsubdir=%destsubdir% %1"
) ELSE (
 REM force at least 2 names
 SET "destsubdir=%1"&shift&GOTO finddest
)
shift
SET "subdirfound="
FOR /f "delims=" %%d IN ('dir /b/ad "%destdir%\%accumsubdir%*" 2^>nul') DO (
 rem if subdirfound is already set, 2 or more exist
 IF DEFINED subdirfound SET "destsubdir=%accumsubdir%"&GOTO finddest
 rem otherwise, record destination subdirectory to use
 SET "subdirfound=%%d"
)

:: none are found or unique has been found - now in subdirfound
:nouniquefound
SET "destsubdir=%subdirfound%"
IF NOT DEFINED destsubdir GOTO :EOF
GOTO :eof

您需要更改sourcedirdestdir的设置以适合您的具体情况。

假设源目录是:

 Volume in drive U has no label.
 Volume Serial Number is BDA0-0000

 Directory of u:\sourcedir

19/09/2016  23:06                 0 q1234
19/09/2016  23:06                 0 Smith John Sign on sheet
19/09/2016  23:06                 0 Robinson Bill Sign on sheet
19/09/2016  23:06                 0 Robinson Bill expenses
19/09/2016  23:06                 0 Robinson George expenses
19/09/2016  23:06                 0 Robinson Fred expenses
19/09/2016  23:06                 0 Jones George expenses
19/09/2016  23:06                 0 von Richthofen Manfred expenses
19/09/2016  23:06                 0 von Richthofen Manfred timesheet
               9 File(s)              0 bytes

目标目录是

 Volume in drive U has no label.
 Volume Serial Number is BDA0-0000

 Directory of u:\destdir

19/09/2016  23:06    <DIR>          .
19/09/2016  23:06    <DIR>          ..
19/09/2016  23:06    <DIR>          Smith John data
19/09/2016  23:06    <DIR>          Robinson Bill data
19/09/2016  23:06    <DIR>          Jones George data
19/09/2016  23:06    <DIR>          von Richthofen Manfred data
19/09/2016  23:06    <DIR>          von Richthofen Lothar data
19/09/2016  23:06    <DIR>          q1234
               0 File(s)              0 bytes

然后运行此批处理产生

q1234: No unique subdir found
MOVE "U:\sourcedir\Smith John Sign on sheet" "U:\destdir\Smith John data\"
MOVE "U:\sourcedir\Robinson Bill Sign on sheet" "U:\destdir\Robinson Bill data\"
MOVE "U:\sourcedir\Robinson Bill expenses" "U:\destdir\Robinson Bill data\"
Robinson George expenses: No unique subdir found
Robinson Fred expenses: No unique subdir found
MOVE "U:\sourcedir\Jones George expenses" "U:\destdir\Jones George data\"
MOVE "U:\sourcedir\von Richthofen Manfred expenses" "U:\destdir\von Richthofen Manfred data\"
MOVE "U:\sourcedir\von Richthofen Manfred timesheet" "U:\destdir\von Richthofen Manfred data\"

使用for的{​​{1}}循环将每个文件名依次分配给%%a,初始化%%a并使用文件名作为参数执行destsubdir

:finddest会将目标目录名分配给:finddest,或者会在destsubdir清除后返回,表示错误。 destsubdir检测到差异,并运行if defined移动文件(目前只是:transfer建议的echo)或报告它无法找到唯一的子目录名称。

move会将名字设置为:finddestdestsubdir,以便下一个名称为shift

如果我们的名字用完了,我们还没找到一个唯一的子目录名称,所以我们退出%1为空。这是destsubdir的情况,因为没有第二个名字。

然后,我们将下一个名称附加到q1234以形成destsubdiraccumsubdir,以删除刚使用的名称。

然后将shift设置为 nothing ,为下一步做好准备。

与累积子目录匹配的每个目录名都分配给subdirfound。如果已设置%%d,则会有2个或更多匹配的名称,因此返回subdirfound以累积下一个名称等。

如果finddest循环完成,则找到一个目标子目录名称(for包含其名称)或者没有(subdirfound仍然为空)。无论哪种方式,我们都可以将subdirfound分配给该值,然后退出子例程。

因此,文件将使用3个名称传输到例如destsubdir,因为von Richthofen Manfred不是唯一的。例如,这可以用来区分约翰·A·史密斯和约翰·B·史密斯,或者范德瓦尔斯·约翰内斯和范德瓦尔斯·雅各布斯之间。