在批处理或powershell脚本中实现Regex以生成文件夹并移动文件名中按键字符串排序的相关文件夹中的文件

时间:2021-12-22 02:23:03

I use a similar script to generate and move files into folders.

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

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

but in my case I want move PDF and different files name and I don't know how solve. Key is title like "Il Corriere dello Sport" withouth suffixes like 02-08-2016 and without -.

但在我的情况下,我想移动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

So I need create folders like

所以我需要创建像

Il_Corriere_dello_Sport_SICILIA
Il_Corriere_di_Arezzo
Il_Giornale_Di_Vicenza
Il_Mattino_di_Padova
Il_Messaggero
Il__Tirreno

P.S: underscore sign _ is not necessary so I prefer replace with space.

P.S:下划线符号_没有必要,所以我更喜欢用空格替换。

and then script must move files relative folders. Finally result should be

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

├─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 个解决方案

#1


1  

Here is a pure solution -- see all the explanatory remarks (rem):

这是一个纯粹的批处理文件解决方案 - 请参阅所有解释性说明(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

The script requires the directory containing all the files to process as the first command line argument. The created sub-directories are placed therein. An optional second command line argument defines a file name pattern to filter certain file types/names. Supposing it is saved as D:\Script\build-folder-hierarchy.bat, the files are contained in D:\Data, and you want to handle *.pdf files only, run it as follows:

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

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

This is a very similar approach, but with a slightly different directory handling:

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

@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

This script uses the current working directory to find the files to process. It requires the target directory as the first command line argument, where the created sub-directories are placed in. An optional second command line argument defines a file name pattern to filter certain file types/names. Supposing it is saved as D:\Script\build-folder-hierarchy.bat, the files are contained in D:\Data and need to be moved to D:\Target, and you want to handle *.pdf files only, run it as follows:

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

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

#1


1  

Here is a pure solution -- see all the explanatory remarks (rem):

这是一个纯粹的批处理文件解决方案 - 请参阅所有解释性说明(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

The script requires the directory containing all the files to process as the first command line argument. The created sub-directories are placed therein. An optional second command line argument defines a file name pattern to filter certain file types/names. Supposing it is saved as D:\Script\build-folder-hierarchy.bat, the files are contained in D:\Data, and you want to handle *.pdf files only, run it as follows:

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

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

This is a very similar approach, but with a slightly different directory handling:

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

@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

This script uses the current working directory to find the files to process. It requires the target directory as the first command line argument, where the created sub-directories are placed in. An optional second command line argument defines a file name pattern to filter certain file types/names. Supposing it is saved as D:\Script\build-folder-hierarchy.bat, the files are contained in D:\Data and need to be moved to D:\Target, and you want to handle *.pdf files only, run it as follows:

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

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