0

我有(并且将有)几个文本文件,需要从每行的前面修剪前 12 个字符。理想情况下,我想要一个批处理文件,在其中输入文件的名称和路径,脚本运行,文件保持相同的名称和位置,或相同的位置,然后在文件名末尾添加“_clean” . 或者,我将 txt 文件放在批处理文件中,或者发生上述两件事之一。

这可能吗?

似乎你可以接近这些例子:

http://social.technet.microsoft.com/Forums/nl/ITCG/thread/2a14d04c-c38b-4a89-95a2-e24aa586849c

使用 Windows 批处理从文件中删除尾随空格?

编辑

有人帮助我做到了这一点:

@echo off 
setlocal enableextensions 
set INFN=%~1 
set OUTFN=%INFN%_clean 
if exist "%OUTFN%" del "%OUTFN%" 
for /f "tokens=1*" %%c in ('type "%INFN%"') do ( 
>> "%OUTFN%" echo %%c %%d 
) 
endlocal

2个问题:

1) 前 12 个字符中有一些文本,所以我需要一些能将前 12 个字符完全切掉的东西。

每行以 2-3 个字符开头,然后是 9-10 个空格,如下所示:

99*10spaces*Text 

或者

100*9spaces*Text 

我只需要文本部分

2) 保存输出文件时,它会在 .txt 扩展名后附加 _clean 保存,即使文件扩展名隐藏。

4

4 回答 4

1

DragAndDrop.bat:看起来一个很好的解决方案是使用单个 .vbs 文件 (DragAndDropTrim12Add_clean.vbs) 中的检查和平衡 (what-if) 功能的单个 .bat 文件 (DragAndDrop.bat)。请参阅下面两个文件的语法。一些额外的脚本被用来保持脚本行相当短。这已更新到 1.1 版,它添加了一个功能,让用户可以选择通过键入新的目标目录来指定。默认有新文件(复制或重命名)假定旧文件的路径。如果选中命令窗口属性快速编辑模式复选框,则可以轻松粘贴到新的目标目录中。输入提示中的向上箭头也将带您返回之前的输入。如果您尝试在非 cScript 模式下运行 DragAndDropTrim12Add_clean.vbs,则会生成弹出消息,但除外,所有用户的焦点都可以保留在命令行上。如果您选择修改 DragAndDrop.bat 文件,请小心避免在 set 命令上添加尾随空格。还建议继续使用 setlocal 调用以减少对周围环境的影响。

:DragAndDropDotBat
 @Title DragAndDrop.bat
  @rem Rev 1.1 11/10/2013 to add optional user specified target directory.
  @rem Labels are followed with "rem :LabelName" for easy GoTo troubleshooting. 
  @rem Script works best if CMD window buffer width set above file lengths.
  @echo off
  @echo ******* THIS IS FILE %0 %DATE% %TIME: =0% ********
  @echo User Choices are not case sensitive.
  @echo Leading or trailing white spaces are trimmed in derived names.
  @echo If Notepad OldFile is selected, the process will loop and run again.

   setlocal
    REM YOU MUST MANUALLY EDIT AND SET THE NEXT LINE PATH!!!!!
     Set FileToCall="x:\Scripts\DragAndDropTrim12Add_clean.vbs"
      Set BatNewFileTargetDir="UseOldFilePath"
       Set Per0=%0
        Set Per0=%Per0:"=%
         Set ProCount=0
          prompt :

:RunProcess
 rem :RunProcess
  Set /A ProCount=%ProCount% + 1

:SameAgain
 rem :SameAgain
  @echo off
   Set BatUserCho=S
    Set ProCntZeroFill=000%ProCount%
     Set strBatMode=
      Set strBatOFFP=
       Set strBatOFNm=
        Set strBatNFFP=
         Set strBatNFNm=
          Set strBatMsgLine0=
           Set BatNewFileTargetDir=%BatNewFileTargetDir%

 @echo ----------------------------------------------------------------
  @echo Process Cmd.%ProCntZeroFill:~-3% for file:  %1
   @echo Key-in e to exit, r to run, s to skip, n to notepad, t to new target dir :
    rem ECHO on
     For /f "tokens=1 delims=" %%a in ('cScript //NoLogo %FileToCall% %1') Do %%a
      If Not #%strBatMode%#==#BatCopyOldToNewThenEraseOld# GoTo PresentUserChoice
       Echo Old File = %strBatOFFP%
        dir "%strBatOFFP%"|findstr /i "%strBatOFNm%"
         Echo New File = %strBatNFFP%
          dir "%strBatNFFP%"|findstr /i "%strBatNFNm%"

:PresentUserChoice
 rem :PresentUserChoice
  @Set /P BatUserCho=%strBatMsgLine0% - Cmd.%ProCntZeroFill:~-3%:[%BatUserCho%]: 
   echo :%BatUserCho%:run-now|findstr /i ":R:" && GoTo RunNow
    echo :%BatUserCho%:exit-now|findstr /i ":E:" && GoTo DoExit
     echo :%BatUserCho%:skip-now|findstr /i ":S:" && GoTo ShiftNow
      echo :%BatUserCho%:notepad-now-and-rerun|findstr /i ":N:" && GoTo NotepadNow
       echo :%BatUserCho%:set-new-target-dir|findstr /i ":T:" && GoTo SetNewTarget
       %echo User Choice: %BatUserCho% not recognized, try again.
        GoTo SameAgain


:RunNow
 rem :RunNow
  If #%strBatMode%#==#BatCopyOldToNewThenEraseOld# GoTo BatCopyOldToNewThenEraseOld
   If #%strBatMode%#==#MsgThenExit# GoTo DoExit
    If #%strBatMode%#==#BatRenameOldToNew# GoTo BatRenameOldToNew
     If #%strBatMode%#==#MsgThenSkip# GoTo ShiftNow

:BatRenameOldToNew
 rem :BatRenameOldToNew
  dir "%strBatOFFP%"|findstr /i "%strBatOFNm%" 
   @echo on
    rename "%strBatOFFP%" "%strBatNFNm%"
     @echo off
      dir "%strBatNFFP%"|findstr /i "%strBatNFNm%"
       If Not Exist "%strBatNFFP%" GoTo BatRenameOldToNewAndNewNotFound
        GoTo ShiftNow

:BatRenameOldToNewAndNewNotFound
 rem :BatRenameOldToNewAndNewNotFound
  @echo New file not found: "%strBatNFFP%" 
   @echo ***** This is a rename failure. ******
    @echo off
     GoTo ShiftNow

:BatRenameOldToNewEnd
 rem :BatRenameOldToNewEnd

:BatCopyOldToNewThenEraseOld
 rem :BatCopyOldToNewThenEraseOld
  dir "%strBatOFFP%"|findstr /i "%strBatOFNm%" 
   dir "%strBatNFFP%"|findstr /i "%strBatNFNm%"
    @echo on
     Copy /-Y "%strBatOFFP%" "%strBatNFFP%"
      @echo off
       dir "%strBatOFFP%"|findstr /i "%strBatOFNm%" 
        dir "%strBatNFFP%"|findstr /i "%strBatNFNm%"
         If Not Exist "%strBatNFFP%"  GoTo BatCopyOldToNewAndNewNotFound
          @echo on
           Erase /P "%strBatOFFP%"
            dir "%strBatOFFP%"|findstr /i "%strBatOFNm%" 
             @echo off
              GoTo ShiftNow

:BatCopyOldToNewAndNewNotFound
 rem :BatCopyOldToNewAndNewNotFound
  @echo New file not found: "%strBatNFFP%" 
   @echo ***** The Delete process was skipped. ******

:BatCopyOldToNewThenEraseOldEnd
 ren :BatCopyOldToNewThenEraseOldEnd

:NotepadNow
 rem :NotepadNow
  rem Notepad FileName will hold bat file, Start Notepad will move on.
   echo on
    @rem Start Notepad "%strBatOFFP%"
     Notepad "%strBatOFFP%"
      @echo off
       GoTo SameAgain

:NotepadNowEnd
 rem :NotepadNowEnd

:SetNewTarget
 rem :SetNewTarget
  echo off
   echo ===============================================
    echo TargetDir=%BatNewFileTargetDir%
     echo Key-in your new targer directory on next line or s to skip:
      Set /P BatTrialTarget=-New Target : 
       echo ::%BatTrialTarget%:skip-now|findstr /i "::S:" && GoTo SameAgain
        Set BatTrialTarget=%BatTrialTarget:"=%
         Set BatTrialTarget=%BatTrialTarget:\\=\%
          Set BatTrialTarget=%BatTrialTarget%#:#
           Set BatTrialTarget=%BatTrialTarget: #:#=#:#%
            Set BatTrialTarget=%BatTrialTarget:\#:#=#:#%
             Set BatTrialTarget=%BatTrialTarget:#:#=%
              dir "%BatTrialTarget%"|findstr /i "Directory.of" && GoTo GoodTDir
               echo This directory not found: "%BatTrialTarget%"
                GoTo SetNewTarget

:GoodTDir
 rem :GoodTDir 
  Set BatNewFileTargetDir="%BatTrialTarget%"
   GoTo SameAgain

:SetNewTargetEnd
 rem :SetNewTargetEnd


:RunNowEnd
 rem RunNowEnd

:ShiftNow
 rem :ShiftNow
  shift
   If #:#%1#:#==#:##:# GoTo DoPause
    GoTo RunProcess

:DoExit
 rem :DoExit
  @echo off
   rem Comment out with rem the next four lines if not wanted.
    echo Call "%Per0%" %1 %2 %3 %4 %5 %6 %7 %8 %9>"%TEMP%\ResumeNext9.bat"
     echo Call "%Per0%" %*>"%TEMP%\ResumeAll.bat"
      echo To Resume: Call "%TEMP%\ResumeNext9.bat"
       echo Or Resume: Call "%TEMP%\ResumeAll.bat"
        endlocal
         ping -n 3 localhost>nul
          GoTo DragAndDropDotBatEnd

:DoPause
 rem :DoPause
  @echo ----------------------------------------------------------------
   echo File %Per0% 
    echo has completed input values [%ProCntZeroFill:~-3%]
     @echo ----------------------------------------------------------------
      endlocal
       Pause

:DragAndDropDotBatEnd



'''DragAndDropTrim12Add_clean.vbs
'''Rev 1.1 11/10/2013 to add optional user specified target directory.
'''Problem Statement: http://stackoverflow.com/questions/11760911/
'''batch-file-that-trims-leading-characters-and-lets-me-save-where-i-want
'''I have (and will have) several text files that need the first 12 characters 
'''trimmed from the front of every line. Ideally, I'd like a batch file where 
'''I input the name and path of the file, the script runs, the file keeps its 
'''same name and location, or same location and you add a "_clean" on the end 
'''of the file name. Or, I drop the txt file on the batch file either one of 
'''the 2 things described above happens.
'''Is this possible?

'''Assuming the existing Directory and File structures look like this:
'''x:\aaa\bbb\c c\2013_11_05_aMyTextFile 05.txt
'''x:\aaa\bbb\c c\2013_11_05_aMyTextFile001.txt
'''x:\aaa\bbb\c c\2013_11_05_aMyTextFile002.txt
'''x:\aaa\bbb\c c\2013_11_05_aMyTextFile003.txt
'''x:\aaa\bbb\c c\2013_11_05_aMyTextFile004.txt
'''x:\aaa\bbb\c c\2013_11_05_bMyTextFile002.txt

'''And you want then to look like this:
'''x:\aaa\bbb\c c\MyTextFile 05_clean.txt
'''x:\aaa\bbb\c c\MyTextFile001_clean.txt
'''x:\aaa\bbb\c c\MyTextFile002_clean.txt
'''x:\aaa\bbb\c c\MyTextFile003_clean.txt
'''x:\aaa\bbb\c c\MyTextFile004_clean.txt

'''And supporting scripts are:
'''x:\Scripts\DragAndDrop.bat
'''x:\Scripts\DragAndDropTrim12Add_clean.vbs

'''To use from File Explorer:
'From File Explorer, highlight the existing files, then right click and choose "Copy" –
'''then drop (paste) them onto x:\Scripts\DragAndDrop.bat
'''This will walk you through the renaming processes.

'DragAndDrop.bat  will call DragAndDropTrim12Add_clean.vbs and invoke the following 
'''     Check processes:
'''1    DragAndDropTrim12Add_clean.vbs is called in CScript mode.
'''2    Script command line values are being passed from bat file to vbs file
'''3    Modified values are passed back to bat file and set by the For loop.
'''4    New trimmed and appended file name does not conflict with an existing file.
'''5    Files passed on the drop-generated command line still exist.
'''6    File to be processed does not already contain the "_clean" string
'''7    File to be processed can support having 12 characters trimmed.
'''8    As each file is processed, the script gives several "User Choice" options. 


'''Bat File Values to pass
'''Set strBatMode=MsgThenExit,MsgThenSkip,BatCopyOldToNewThenEraseOld,BatRenameOldToNew
'''Set strBatOFFP=strOldFileFullPath
'''Set strBatOFNm=strOldFileName
'''Set strBatNFFP=strNewFileFullPath
'''Set strBatNFNm=strNewFileName
'''Set strBatMsgLine0=Note:Do not use double quote.


   Option Explicit ''Requires that you dimension all variables
   Dim funInStrVal, funLastHitVal, StdOut, StdErr, objFSO, strWScriptArg0 
   Dim intLastHit, intLenMinus, intTrimLeadNum, strTrailString
   Dim objDialog, intReturn, strMsg1, strNewFileFullPath, strNFN, strTrS
   Dim strOldFileFullPath, strOldFilePath, strOldFileName, strOldFileNameNoExt
   Dim strNewFileName, strS, wshShell, strBatNewFileTargetDir

   If InStr(1,LCase(WScript.FullName),"cscript.exe",1) = 0 Then
      Dim objShell, Rsp01
      Set objShell = WScript.CreateObject("WScript.Shell")
      Rsp01 = objShell.Popup("This script must be run using cScript" _
      & vbCrLf & "Error from " & Wscript.ScriptFullName & vbCrLf _
      & "Use: cScript //NoLogo """ & Wscript.ScriptFullName _
      & """",10,"     Error Because Not Using cScript " _
      & "(10 sec timeout)",vbOKOnly + vbCritical)
      Set objShell = Nothing
      Wscript.Quit
   End If


   intTrimLeadNum = 12
   strTrailString = "_clean"
   ''Set StdIn = WScript.StdIn
   Set StdOut = WScript.StdOut
   Set StdErr = WScript.StdErr
   Set wshShell = CreateObject( "WScript.Shell" )

   strBatNewFileTargetDir = wshShell.ExpandEnvironmentStrings( "%BatNewFileTargetDir%" )
   Set wshShell = Nothing
   strBatNewFileTargetDir = Replace(strBatNewFileTargetDir,"""","") ''remove dq



   If WScript.Arguments.Count > 0 Then
      strWScriptArg0=Trim(WScript.Arguments.Item(0))
   Else
      strMsg1="NO Command Line" _
      & " value passed to: " & Wscript.ScriptFullName
      StdErr.WriteLine "WARNING: " & strMsg1 
      StdOut.WriteLine "Set BatUserCho=E"
      StdOut.WriteLine "Set strBatMode=MsgThenExit"
      StdOut.WriteLine "Set strBatMsgLine0=.........................Press Enter to Exit"
      Wscript.Quit
   End If

   Set objFSO = CreateObject("Scripting.FileSystemObject")

   If objFSO.FileExists(strWScriptArg0) = False Then
      strMsg1 = strWScriptArg0 & " is not a valid file name."
      StdErr.WriteLine "WARNING: " & strMsg1 
      StdOut.WriteLine "Set BatUserCho=S"
      StdOut.WriteLine "Set strBatMode=MsgThenSkip"
      StdOut.WriteLine "Set strBatMsgLine0=.........................Press Enter to Skip"
      Set objFSO = Nothing
      Wscript.Quit
   End If


      strOldFileFullPath = strWScriptArg0
      strOldFilePath = FunLeftOrRtStr(strOldFileFullPath, "\", "L")
      strS = strOldFileFullPath  ''Short String for using less columns
      strOldFileName = Right(strS,Len(strS) - (FunLastHitInt(strS, "\") + 1))
      strOldFileNameNoExt = Trim(FunLeftOrRtStr(strOldFileName, ".", "L"))
      strNFN=strOldFileNameNoExt
      strTrS=strTrailString &  "." & FunLeftOrRtStr(strOldFileName, ".", "R")




   If Len(strOldFileNameNoExt) <= intTrimLeadNum Then 
      strMsg1 = strOldFileFullPath & " Base File Name is:" & vbCrLf & Len(strOldFileNameNoExt) _
      & " characters which is too short for the " & intTrimLeadNum & " char trim."
      StdErr.WriteLine "WARNING: " & strMsg1 
      StdOut.WriteLine "Set BatUserCho=S"
      StdOut.WriteLine "Set strBatMode=MsgThenSkip"
      StdOut.WriteLine "Set strBatMsgLine0=.........................Press Enter to Skip"
      StdOut.WriteLine "Set strBatOFFP=" & strOldFileFullPath
      StdOut.WriteLine "Set strBatOFNm=" & strOldFileName
      Set objFSO = Nothing
      Wscript.Quit
   End If

      ''Remove any leading or trailing white space with Trim()
      strNewFileName = Trim(Right(strNFN, Len(strNFN) - intTrimLeadNum)) & strTrS

 StdErr.WriteLine "strBatNewFileTargetDir=" & strBatNewFileTargetDir

   If strBatNewFileTargetDir = "UseOldFilePath" Or InStr(1,strBatNewFileTargetDir, "\") = 0 Then
      strNewFileFullPath = strOldFilePath & "\" & strNewFileName
   Else
      strNewFileFullPath = strBatNewFileTargetDir & "\" & strNewFileName
   End If

   If objFSO.FileExists(strNewFileFullPath) = True Then
      StdErr.WriteLine "WARNING: " & strNewFileName & " existing."
      StdOut.WriteLine "Echo You can Copy Old and overwrite Existing"
      StdOut.WriteLine "Echo You will be prompted for the Overwrite:"
      StdOut.WriteLine "Echo You will also be prompted for the Delete:"
      StdOut.WriteLine "Set strBatMode=BatCopyOldToNewThenEraseOld"
      StdOut.WriteLine "Set BatUserCho=R"
      StdOut.WriteLine "Set strBatMsgLine0=..Press Enter to Copy Old to New Then Delete Old"
      StdOut.WriteLine "Set strBatOFFP=" & strOldFileFullPath
      StdOut.WriteLine "Set strBatOFNm=" & strOldFileName
      StdOut.WriteLine "Set strBatNFFP=" & strNewFileFullPath
      StdOut.WriteLine "Set strBatNFNm=" & strNewFileName
      Set objFSO = Nothing
      Wscript.Quit
   Else
      StdOut.WriteLine "Echo Old File = " & strOldFileFullPath
      If InStr(1,strOldFileName, strTrailString) > 0 Then
         strMsg1 = strOldFileName & " already contains: " & strTrailString
         StdErr.WriteLine "***WARNING: " & strMsg1 & "***"
         StdOut.WriteLine "Echo New File Would = " & strNewFileFullPath
         StdOut.WriteLine "Set BatUserCho=S"
         StdOut.WriteLine "Echo...........Key-in r to RUN and Rename Old to New. "
         StdOut.WriteLine "Set strBatMsgLine0=................... or Press Enter to Skip" 
      Else
         StdOut.WriteLine "Echo New File = " & strNewFileFullPath
         StdOut.WriteLine "Set BatUserCho=R"
         StdOut.WriteLine "Set strBatMsgLine0=...........Rename Old to New---Press " _
         & "Enter to RUN"
      End If
      StdOut.WriteLine "Set strBatMode=BatRenameOldToNew"
      StdOut.WriteLine "Set strBatOFFP=" & strOldFileFullPath
      StdOut.WriteLine "Set strBatOFNm=" & strOldFileName
      StdOut.WriteLine "Set strBatNFFP=" & strNewFileFullPath
      StdOut.WriteLine "Set strBatNFNm=" & strNewFileName
   End If



   If 1 = 2 Then  ''''Change to 1 = 1 for testing.  StdErr will not go to bat file
      Dim strInVal, strTFileName, strTNewFile, strTFileNameNoExt, strTFileExt
      ''strInVal = "X:\aaa\bbb\c c\12345.678"
      strInVal = strWScriptArg0
      intLastHit = FunLastHitInt(strInVal, ".")
      StdErr.WriteLine " :  strInVal=" & strInVal
      StdErr.WriteLine " : Path+File=" & Left(strInVal,intLastHit)
      StdErr.WriteLine " : Ext=" & Right(strInVal,Len(strInVal) - intLastHit)
      StdErr.WriteLine " : Path=" & FunLeftOrRtStr(strInVal, "\", "L")
      StdErr.WriteLine " :      FileName=" & FunLeftOrRtStr(strInVal, "\", "R")
      strTFileName=Right(strInVal,Len(strInVal) - (FunLastHitInt(strInVal, "\") + 1))
      strTFileNameNoExt = FunLeftOrRtStr(strTFileName, ".", "L")
      strTFileExt="." & FunLeftOrRtStr(strInVal, ".", "R")
      StdErr.WriteLine " : FileNameNoExt=" &  strTFileNameNoExt
      StdErr.WriteLine " :           Ext=" & strTFileExt
      strTNewFile=Right(strTFileNameNoExt, Len(strTFileNameNoExt) - intTrimLeadNum)
      StdErr.WriteLine " :       NewFile=" & strTNewFile & strTrailString & strTFileExt

   End If ''If 1 = 2 Then



   Function FunLastHitInt(funInputString, funHitChar)
    '''Dim funInStrVal, funLastHitVal (Required at top of script)
    '''For Dir Use: Left(strFullPath,FunLastHitInt(strFullPath, "\"))
    ''For File Use: 
    ''Right(strFullPath,Len(strFullPath) - (FunLastHitInt(strFullPath, "\") + 1))
    If InStr(1,funInputString, funHitChar) > 0 Then
       funInStrVal = 2
       Do Until funInStrVal = 1 ''funLastHitVal will eventually = 0 + 1
          funLastHitVal = InStr(funInStrVal, funInputString, funHitChar)
          If funLastHitVal > 0 Then
             FunLastHitInt = funLastHitVal - 1
          End If
          funInStrVal = funLastHitVal + 1
          ''Wscript.Echo "funLastHitVal=" & funLastHitVal
       Loop
    Else
       FunLastHitInt = 0
    End If
   End Function ''Function FunLastHitInt(funInputString, funLastChar)


   Function FunLeftOrRtStr(funFullPathLR, funHitCharLR, funLorR)
    If InStr(1,funFullPathLR,funHitCharLR) = 0 Then
       FunLeftOrRtStr = funFullPathLR
    ElseIf UCase(funLorR) = "R" Then
       intLenMinus = (FunLastHitInt(funFullPathLR, funHitCharLR) + Len(funHitCharLR))
       FunLeftOrRtStr = Right(funFullPathLR,Len(funFullPathLR) - intLenMinus)
    Else
       FunLeftOrRtStr = Left(funFullPathLR,FunLastHitInt(funFullPathLR, funHitCharLR))
    End If
   End Function


  Set objFSO = Nothing
  Wscript.Quit

'''DragAndDropTrim12Add_clean.vbsEnd
于 2013-11-10T17:06:05.970 回答
1

如果您只想截断输入文件每一行的前 12 个字符,cut来自UnxUtils http://unxutils.sourceforge.net/是您的朋友。

看看cut --help然后试试这个简单的单行 bat 文件

cut -c13- %1 >%~dpn1_CLEAN%~x1
于 2012-08-01T16:10:54.540 回答
1

这是一种使用本机批处理命令修剪每一行的方法。

更新

修改了构建输出文件名的代码。

@ECHO OFF

SETLOCAL EnableExtensions EnableDelayedExpansion

SET INFN=%1
SET OUTFN=%~n1_clean%~x1

IF EXIST "%OUTFN%" DEL "%OUTFN%"

FOR /F "tokens=* usebackq" %%c IN (%INFN%) DO (
  SET RESULT=%%c
  SET RESULT=!RESULT:~12!
  REM Displays the trimmed line in the console window
  ECHO !RESULT!
  REM Writes the trimmed line to the output file
  ECHO !RESULT!>>"%OUTFN%"
)

ENDLOCAL
于 2012-08-01T19:18:38.637 回答
0

我把这个问题放到另一个网站上,以下是我们最终完全按照我想要的方式工作:

@echo off
if not exist "%~1" (echo Error & pause & exit /b 1) 
echo do until wsh.stdin.atendofstream:wsh.echo mid(wsh.stdin.readline, 9):loop> %temp%\_t.vbs
more /T8 < "%~1" | cscript //nologo %temp%\_t.vbs > "%~dpn1_clean%~x1"
del %temp%\_t.vbs
del %1

再次感谢大家的帮助。

于 2012-08-02T18:05:03.947 回答