从子字符串结果中删除可能的尾随空格

Posted

技术标签:

【中文标题】从子字符串结果中删除可能的尾随空格【英文标题】:Remove possible trailing spaces from a substring result 【发布时间】:2021-10-23 01:03:46 【问题描述】:

我在批处理脚本方面缺乏经验,并且刚刚编写了一个枚举源目录中所有文件的脚本,并且每个文件名字符串都被修剪到其第一个 - 字符。然后检查目标路径是否存在使用结果子字符串命名的子目录,如果未找到匹配项,则创建该目录。然后将源文件移动到该目录中。

我的问题是文件名字符串通常在 - 之前包含空格,这会导致子字符串带有尾随空格字符。

所以我的问题是,如何在使用包含它们的子字符串之前删除尾随空格字符。

到目前为止的代码:

REM CODE BY ZF

@Echo off
CLS
setlocal
SETLOCAL ENABLEDELAYEDEXPANSION

set /p Input=ENTER DIRECTORY: 

REM set mypath=%Input%

REM *******************
REM IFIXED PATH FOR TESTING
set mypath=C:\Admin\cmd_tests

REM echo !mypath!
REM pause
IF "%mypath%" NEQ "" (

    REM set mypath=C:\Admin\cmd_tests
    REM pause
    REM *******************
    REM GET SUBFOLDERNAME FROM FILENAME - WORKS
    set Counter=0
    for %%f in (%mypath%\*.*) do (
        echo %%f
        echo %%~nxf
        for /f "delims=-" %%i in ("%%~nxf") do (
            REM echo %%i
            set myfolder=%%i
            set %%myfolder=myfolder
        )
        echo !myfolder!

        REM set "MYSTRING=%%myfolder"
        REM *******************
        REM ITERATE FOLDER NAME - myfolder is not transfered into this routine, so the result = "" and ""
        (echo %myfolder%& echo.) | findstr /O . | more +1 | (set /P RESULT= & call exit /B %%RESULT%%)
        set /A STRLENGTH=%ERRORLEVEL%-5
        echo string !myfolder! length = %STRLENGTH%

        REM *******************
        REM DEFINE TARGET SUBFOLDER PATH
        set searchfolder="C:\Admin\cmd_tests\!myfolder!"
        echo !searchfolder!

        REM if exist !searchfolder! echo "Folder already exists"
        REM if not exist !searchfolder! echo "Folder does not exist"
        REM *******************
        REM CREATE SUBFOLDER
        if not exist !searchfolder! mkdir !searchfolder!

        REM *******************
        REM DEFINE FILE
        set targetfile="C:\Admin\cmd_tests\!myfolder!\%%~nxf"
        echo !targetfile!

        REM *******************
        REM MOVE FILE TO SUBFOLDER
        IF NOT EXIST "%searchfolder%\%%~NXF" (
            echo "FILE DOES NOT EXIST"

            REM move "%%f" "%targetfile%"
        ) ELSE (
            echo "FILE EXISTS"
        )
        echo "---------------------"
    )
    pause
) ELSE (

    REM *******************
    REM IF MYPATH DIESN EXIST (user input later)
    echo "exit"
    pause
)

【问题讨论】:

你好,我只是通过 for /f "tokens=* delims= " %%a in ("%MYSTRING%") 对变量进行冷修,为 /l %% 设置 MYSTRING=%%a a in (1,1,100) do if "!MYSTRING:~-1!"==" " set MYSTRING=!MYSTRING:~0,-1!所以现在路径是正确的:-) 去掉set %%myfolder=myfolder这行,这里错了也没用,它把字符串值myfolder赋给一个名为%myfolder的变量... 为什么不替换 [space + - + space] 或 [space + - ] 通过- 拆分字符串?我认为这会让生活更轻松…… 【参考方案1】:

我做到了 - 文件现在已正确移动:

代码 V2/WIP:

REM CODE BY Zdenek Fajfrlik & adapted info from the forum

@Echo off
CLS
SETLOCAL ENABLEDELAYEDEXPANSION
set /p Input=ENTER DIRECTORY: 

REM set mypath=%Input%
REM *******************
REM FIXED PATH FOR TESTING
set mypath=C:\Admin\cmd_tests

IF NOT "%mypath%" == "" (

    REM *******************
    REM GET SUBFOLDERNAME FROM FILENAME - WORKS
    set Counter=0
    for %%f in (%mypath%\*.*) do (

        REM echo %%f
        REM echo %%~nxf
        for /f "delims=-" %%i in ("%%~nxf") do (
            set MYSTRING=%%i
        )

        REM *******************
        REM TRIM STRING - TRAILING SPACES
        REM ::trim right whitespace (up to 100 spaces at the end)
        for /f "tokens=* delims= " %%a in ("%MYSTRING%") do set MYSTRING=%%a
        for /l %%a in (1,1,100) do if "!MYSTRING:~-1!"==" " set MYSTRING=!MYSTRING:~0,-1!

        REM echo !MYSTRING!
        REM *******************
        REM DEFINE TARGET SUBFOLDER PATH
        set searchfolder="C:\Admin\cmd_tests\!MYSTRING!"
        echo !searchfolder!

        REM if exist !searchfolder! echo "Folder already exists"
        REM if not exist !searchfolder! echo "Folder does not exist"
        REM *******************
        REM CREATE SUBFOLDER
        if not exist !searchfolder! mkdir !searchfolder!

        REM *******************
        REM DEFINE FILE
        REM set targetfile=C:\Admin\cmd_tests\!MYSTRING!\%%~nxf
        set targetfile="C:\Admin\cmd_tests\!MYSTRING!\%%~nxf"

        REM echo !targetfile!
        REM *******************
        REM MOVE FILE TO SUBFOLDER
        IF NOT EXIST "%searchfolder%\%%~NXF" (
            echo "FILE DOES NOT EXIST"
            echo %%f
            echo !targetfile!
            move "%%f" !targetfile! 
        ) ELSE (
            echo "FILE EXISTS"
        )
        echo "---------------------"
    )
    pause
) ELSE (

    REM *******************
    REM IF MYPATH DOES NOT EXIST (user input later)
    echo "exit"
    pause
)

感谢您的帮助:-)

斯坦

【讨论】:

我强烈建议您也查看我的代码。我使用您的代码,将set mypath=C:\Admin\cmd_tests 修改为set "mypath=C:\Temp\Development & Test()^!",并将所有其他C:\Admin\cmd_tests 替换为C:\Temp\cmd_tests。我在文件夹C:\Temp\Development & Test()! 中有文件.Unsual File Name - Test!;test file - folder.tmp(开头有两个空格)和test folder - folder.tmp,并且批处理文件的执行导致批处理文件处理退出的早期状态并出现错误留言& was unexpected at this time. 因此,对于不包含空格或其中一个字符 &()[]^=;!'+,`~ 的文件夹路径和不包含对 cmd.exe 具有特殊含义的字符的文件名,批处理文件现在可能对您偶然起作用, 但它的编码绝对不够好,无法在所有可能的目录和文件名的每台 Windows 计算机上使用。 嗨,是的。与此同时,我重新激活了路径的用户输入 - 所以我从资源管理器复制文件夹的路径并在脚本中进行输入。实际上,接下来是特殊字符。目前,我使用下划线保持所有路径没有空格,所以一切正常,但你是对的,还有更多需要开发。我必须先了解更多,但目前它有效。现在从论坛中删除我的代码会更好吗,因为它非常简单且不保存?谢谢斯坦【参考方案2】:

以下批处理文件可用于将指定文件夹中的所有非隐藏文件移动到子文件夹中,其名称可以是整个文件名,也可以是直到第一个连字符的字符串,也适用于以点开头的异常文件名并执行没有文件扩展名(= 一个点,最后一个点后至少有一个字符)。

Windows 文件管理从文件/文件夹名称中删除尾随空格和点,如 Microsoft 在关于 Naming Files, Paths, and Namespaces 的页面上所述。出于这个原因,批处理文件使用 Windows 文件管理功能来获取没有尾随空格和点的文件夹名称,而不是使用自己的代码从文件名上的文件夹名称中删除尾随空格,例如 album name - song title.mp4 来移动文件到名为 album name 的子文件夹。

@echo off
setlocal EnableExtensions DisableDelayedExpansion
cls
rem Assign the first argument string passed to the batch file
rem on calling it to the environment variable FolderPath.
set "FolderPath=%~1"
rem Is the batch file not called with an argument string?
if not defined FolderPath goto FolderPrompt
rem Replace all slashes by backslashes in the passed argument string.
set "FolderPath=%FolderPath:/=\%"
rem Append a backslash if the passed argument string does not end
rem with a backslash and check next if the passed argument string
rem references an existing folder at all.
if not "%FolderPath:~-1%" == "\" set "FolderPath=%FolderPath%\"
if not exist "%FolderPath%" goto FolderPrompt
rem Get the full folder path with a backslash at end
rem if the passed folder path is a relative path.
for %%I in ("%FolderPath%") do set "FolderPath=%%~fI"
goto ProcessFiles

:FolderPrompt
rem Undefine the environment variable FolderPath.
set "FolderPath="
rem Prompt the user for the folder path.
set /P "FolderPath=Enter directory: "
rem Has the user not entered a string?
if not defined FolderPath goto FolderPrompt
rem Remove all double quotes from user input string.
set "FolderPath=%FolderPath:"=%"
rem Has the user not entered anything else than one or more double quotes?
if not defined FolderPath goto FolderPrompt
rem Replace all slashes by backslashes in user input string.
set "FolderPath=%FolderPath:/=\%"
rem Append a backslash if the passed argument string does not end
rem with a backslash and check next if the passed argument string
rem references an existing folder at all.
if not "%FolderPath:~-1%" == "\" set "FolderPath=%FolderPath%\"
if not exist "%FolderPath%" goto FolderPrompt
rem Get the full folder path with a backslash at end
rem if the entered folder path is a relative path.
for %%I in ("%FolderPath%") do set "FolderPath=%%~fI"
goto ProcessFiles

rem Process all non-hidden files in the folder with first loading into
rem memory the list of file names of the files to move to subfolders to
rem make sure that no file is skipped as it could happen on processing
rem the files just a simple FOR loop on FAT32 or exFAT drives.

rem For each file name the string up to first hyphen characters is
rem interpreted as folder name into which the file should be moved.
rem The entire file name is interpreted as folder name if the file name
rem does not contain a hyphen character at all. The extra IF condition
rem is for file names starting with a dot and not having a file extension
rem like ".Unsual File Name - Test!".

rem The Windows file management removes by default all trailing spaces and
rem dots before passing a file/folder name to the file system. Therefore
rem the Windows file management functions are used implicit to get the
rem folder name as either already existing for the current file or being
rem next created without trailing spaces and dots with using the third
rem FOR loop with loop variable K. The usage of "%%~nxK" results in passing
rem the folder name via Windows file management API to the file system and
rem so this reference expands to folder name as returned by the file system
rem (folder exists) respectively the used Windows file managment function
rem (folder does not exist).

:ProcessFiles
echo Process files in: "%FolderPath:~0,-1%"
for /F "eol=| delims=" %%I in ('dir "%FolderPath%*" /A-D-H /B 2^>nul') do (
    if not "%%~nI" == "" (
        for /F "eol=| delims=-" %%J in ("%%~nI") do for %%K in ("%%J") do (
            md "%FolderPath%%%~nxK" 2>nul
            if exist "%FolderPath%%%~nxK\" (
                echo Move "%%I" to "%%~nxK" ...
                move /Y "%FolderPath%%%I" "%FolderPath%%%~nxK\"
            ) else echo ERROR: Failed to create directory: "%%~nxK"
        )
    ) else (
        for /F "eol=| delims=-" %%J in ("%%~xI") do for %%K in ("%%J") do (
            md "%FolderPath%%%~nxK" 2>nul
            if exist "%FolderPath%%%~nxK\" (
                echo Move "%%I" to "%%~nxK" ...
                move /Y "%FolderPath%%%I" "%FolderPath%%%~nxK\"
            ) else echo ERROR: Failed to create directory: "%%~nxK"
        )
    )
)
endlocal

嗯,这个批处理文件显然应该用于移动歌曲或视频文件,但设计用于移动任何类型的文件。

包含要移动的文件的文件夹的路径可以作为调用它的第一个参数传递给批处理文件,例如,通过 Windows 文件中的 发送到 上下文菜单使用此批处理文件资源管理器右键单击文件夹,或者可以在执行批处理文件时输入。请阅读 cmets 批处理文件如何确保传递或输入的参数字符串是具有完整或相对路径的文件夹的名称。传递或输入的文件夹路径也可以是\MySongs(当前驱动器根目录中的文件夹MySongs)或..\MyVideos(当前目录父目录中的文件夹MyVideos)。

批处理文件不使用延迟的环境变量扩展,因此也适用于包含一个或多个! 的文件名。它也适用于以一个或多个空格或分号开头的文件名。

要了解所使用的命令及其工作原理,请打开command prompt 窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

cls /? dir /? echo /? endlocal /? for /? goto /? if /? md /? move /? rem /? set /? setlocal /?

阅读有关Using command redirection operators 的Microsoft 文档以了解2>nul 的解释。重定向运算符 > 必须在 FOR 命令行上使用插入字符 ^ 转义,以便在 Windows 命令解释器在执行命令 FOR 之前处理此命令行时解释为文字字符> 在后台启动的单独命令进程中执行嵌入的dir 命令行。

【讨论】:

以上是关于从子字符串结果中删除可能的尾随空格的主要内容,如果未能解决你的问题,请参考以下文章

如何删除前导和尾随的空格以及字符串中的多个空格? [复制]

从字符串值中删除空格(前导和尾随)

删除json字符串c#中的尾随空格

Javascript从多行字符串中删除前导和尾随空格

SQL Server从字符串中删除尾随空格

Android/Java 正则表达式从子字符串中删除多余的零