在批处理或powershell脚本中实现Regex,以生成文件夹,并按文件名

时间:2016-09-15 20:46:37

标签: powershell batch-file

我使用类似的脚本生成文件并将其移动到文件夹中。

$ToFolder = "$env:USERPROFILE\Desktop\to"
$FromFolder = "$env:USERPROFILE\Desktop\From"

#Create the sample folder on your desktop
#This line can be commented out if your ToFolder exists
New-Item $ToFolder -ItemType directory -Force

GCI -Path $FromFolder *.torrent | % {
    if ($_.Name -match "(19|20)\d{2}") {

        #Check to see if year folder already exists at the destination
        #If not then create a folder based on this year
        if (!(Test-Path "$ToFolder\$($Matches[0])")) {
            New-Item -Path "$ToFolder\$($Matches[0])" -ItemType directory
        }

        #Transfer the matching file to its new folder
        #Can be changed to Move-Item if happy with the results
        Copy-Item -Path $_.FullName -Destination "$ToFolder\$($Matches[0])" -Force
    }
}

但在我的情况下,我想要移动PDF和不同的文件名,我不知道如何解决。关键是标题如" Il Corriere dello Sport"没有后缀,如02-08-2016,没有-

Il_Corriere_dello_Sport_SICILIA_-_02-08-2016HQ
Il_Corriere_dello_Sport_STADIO_-_02-08-2016HQ
Il_Corriere_di_Arezzo_-_31-08-2016MQ
Il_Giornale_Di_Vicenza_-_23-08-2016
Il_Mattino_di_Padova_-_23-08-2016
Il_Messaggero_-_02-08-2016
Il_Messaggero_-_23-08-2016
Il__Messaggero_Veneto_-_31-08-2016HQ
Il__Tirreno_-_31-08-2016HQ
Il_Centro_-_30-08-2016
Il_Centro_CHIETI_-_23-08-2016HQ

所以我需要创建像

这样的文件夹
Il_Corriere_dello_Sport_SICILIA
Il_Corriere_di_Arezzo
Il_Giornale_Di_Vicenza
Il_Mattino_di_Padova
Il_Messaggero
Il__Tirreno

P.S:下划线符号_不是必需的,所以我更喜欢用空格替换。

然后脚本必须移动文件相对文件夹。最后结果应该是

├─Il Messaggero [folder]
│ ├─Il_Messaggero_-_02-08-2016 [file]
│ └─Il_Messaggero_-_23-08-2016 [file]
├─Il Messaggero Veneto [folder]
│ └─Il__Messaggero_Veneto_-_31-08-2016HQ [file]
:

1 个答案:

答案 0 :(得分:1)

这是一个纯粹的解决方案 - 请参阅所有解释性说明(rem):

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "SPLITCHAR=-"  & rem // (a single character to split the file names)
set "SEARCHSTR=_"  & rem // (a certain string to be replaced by another)
set "REPLACSTR= "  & rem // (a string to replace all found search strings)
set "OVERWRITE="   & rem // (set to non-empty value to force overwriting)

rem // Get file location and pattern from command line arguments:
set "LOCATION=%~1" & rem // (directory containing files to process)
set "PATTERNS=%~2" & rem // (file pattern; match all files if empty)

rem /* Prepare overwrite flag (if defined, set to character forbidden
rem    in file names; this affects later check for file existence): */
if defined OVERWRITE set "OVERWRITE=|"
rem // Continue only if location is given:
if defined LOCATION (
    rem // Change current working directory to given location:
    pushd "%LOCATION%" && (
        rem // Loop through all files matching the given pattern:
        for /F "eol=| delims=" %%F in ('dir /B "%PATTERNS%"') do (
            rem // Process each file in a sub-routine:
            call :PROCESS "%%F" "%SPLITCHAR%" "%SEARCHSTR%" "%REPLACSTR%"
        )
        rem // Restore former working directory:
        popd
    )
)

endlocal
exit /B


:PROCESS
rem // Retrieve first argument of sub-routine:
set "FILE=%~1"
rem // Split name at (first) split character and get portion in front:
for /F "delims=%~2" %%E in ("%~1") do (
    rem // Append a split character to partial name:
    set "FOLDER=%%E%~2"
)
setlocal EnableDelayedExpansion
rem // Right-trim partial name:
if not "%~3"=="" set "FOLDER=!FOLDER:%~3%~2=!"
set "FOLDER=!FOLDER:%~2=!"
rem /* Check whether partial name is not empty
rem    (could happen if name began with split character): */
if defined FOLDER (
    rem // Replace every search string with another:
    if not "%~3"=="" set "FOLDER=!FOLDER:%~3=%~4!"
    rem // Create sub-directory (surpress error if it already exists):
    2> nul md "!FOLDER!"
    rem /* Check if target file already exists; if overwrite flag is
    rem    set (to an invalid character), the target cannot exist: */
    if not exist "!FOLDER!\!FILE!%OVERWRITE%" (
        rem // Move file finally (surpress `1 file(s) moved.` message):
        1> nul move /Y "!FILE!" "!FOLDER!"
    )
)
endlocal
exit /B

该脚本要求包含要处理的所有文件的目录作为第一个命令行参数。创建的子目录放在其中。可选的第二个命令行参数定义文件名模式以过滤某些文件类型/名称。假设它保存为D:\Script\build-folder-hierarchy.bat,文件包含在D:\Data中,您只想处理*.pdf个文件,运行方式如下:

"D:\Script\build-folder-hierarchy.bat" "D:\Data" "*.pdf"

这是一种非常类似的方法,但目录处理略有不同:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "SPLITCHAR=-"  & rem // (a single character to split the file names)
set "SEARCHSTR=_"  & rem // (a certain string to be replaced by another)
set "REPLACSTR= "  & rem // (a string to replace all found search strings)
set "OVERWRITE="   & rem // (set to non-empty value to force overwriting)

rem // Get file location and pattern from command line arguments:
set "LOCATION=%~1" & rem // (directory to move the processed files into)
set "PATTERNS=%~2" & rem // (file pattern; match all files if empty)

rem /* Prepare overwrite flag (if defined, set to character forbidden
rem    in file names; this affects later check for file existence): */
if defined OVERWRITE set "OVERWRITE=|"
rem // Continue only if target location is given:
if defined LOCATION (
    rem // Create target location (surpress error if it already exists):
    2> nul md "%LOCATION%"
    rem /* Loop through all files matching the given pattern
    rem    in the current working directory: */
    for /F "eol=| delims=" %%F in ('dir /B "%PATTERNS%"') do (
        rem // Process each file in a sub-routine:
        call :PROCESS "%%F" "%LOCATION%" "%SPLITCHAR%" "%SEARCHSTR%" "%REPLACSTR%"
    )
)

endlocal
exit /B


:PROCESS
rem // Retrieve first argument of sub-routine:
set "FILE=%~1"
rem // Split name at (first) split character and get portion in front:
for /F "delims=%~3" %%E in ("%~1") do (
    rem // Append a split character to partial name:
    set "FOLDER=%%E%~3"
)
setlocal EnableDelayedExpansion
rem // Right-trim partial name:
if not "%~4"=="" set "FOLDER=!FOLDER:%~4%~3=!"
set "FOLDER=!FOLDER:%~3=!"
rem /* Check whether partial name is not empty
rem    (could happen if name began with split character): */
if defined FOLDER (
    rem // Replace every search string with another:
    if not "%~4"=="" set "FOLDER=!FOLDER:%~4=%~5!"
    rem // Create sub-directory (surpress error if it already exists):
    2> nul md "%~2\!FOLDER!"
    rem /* Check if target file already exists; if overwrite flag is
    rem    set (to an invalid character), the target cannot exist: */
    if not exist "%~2\!FOLDER!\!FILE!%OVERWRITE%" (
        rem // Move file finally (surpress `1 file(s) moved.` message):
        1> nul move /Y "!FILE!" "%~2\!FOLDER!"
    )
)
endlocal
exit /B

此脚本使用当前工作目录查找要处理的文件。它需要将目标目录作为第一个命令行参数,其中放置已创建的子目录。可选的第二个命令行参数定义文件名模式以过滤某些文件类型/名称。假设它保存为D:\Script\build-folder-hierarchy.bat,文件包含在D:\Data中,需要移动到D:\Target,并且您只想处理*.pdf个文件,运行方式如下:

cd /D "D:\Data"
"D:\Script\build-folder-hierarchy.bat" "D:\Target" "*.pdf"