为什么在调用其他脚本时没有传递感叹号?

时间:2017-08-30 22:57:33

标签: batch-file special-characters

这是我的两个脚本的输出。第一个调用另一个并传递文件名为%1

D:\VIDEOS\SHORTS>for %v in (*) do call namer "%v"

D:\VIDEOS\SHORTS>call namer "10 Products You’ll Never Buy Again Knowing How They Are Made!.mp4"

D:\VIDEOS\SHORTS>echo "10 Products You’ll Never Buy Again Knowing How They Are Made.mp4"   | find /i ".tmp"   1>nul  && exit /b

echo使用"%~nx1"

我的问题是:为什么感叹号会消失?

这种情况昨天开始发生,但我不确定我能做些什么才能做到这一点。它是大规模批处理脚本群集的一部分,由于大小限制,我无法在此发布所有内容,因此请求了解更多详细信息或进行概括。

编辑:请求的文件namer.cmd

set "full=" & set "file=" & set "name=" & set "type=" & set "year=" & set "episode=" & set "strict=" & set "loose="
echo "%~nx1" | find /i ".tmp" >nul && exit /b
set "file=%~n1"

:: =============================================================================================================================
::      1. file VALIDATOR
:: =============================================================================================================================

set "original=%file%"
set "file=%file:!=%"
set "file=%file:#=%"
set "file=%file: _ = - %"
set "file=%file:’='%"
set "file=%file:“='%"
set "file=%file:”='%"
set "file=%file:[=(%"
set "file=%file:]=)%"
set "file=%file:_= %"
set "file=%file:—=-%"
set "file=%file:  = %"
set "file=%file:  = %"
set "file=%file:&=and%"

:: exclamation point has to be removed before we enable delayed expansion
if not "%file%"=="%original%" ren "%~1" "%file%%~x1" 2>nul && echo validated "%file%%~x1"
if not "%file%"=="%original%" if exist "%original%" ren "%~1" "%file% - copy%~x1" && echo validated "%file% - copy%~x1"
if not "%file%"=="%original%" if exist "%original%" ren "%~1" "%file% - copy 2%~x1" && echo validated "%file% - copy 2%~x1"

setlocal enabledelayedexpansion
set "original=!file!"
set "file=!file:%%=_percent!"
if not "%file%"=="%original%" ren "%~dp1%original%%~x1" "for /f "delims=" %%v in ('where /r "d:\videos" "%strict%*" 2^>nul') do" && echo validated "%original%"

set "original=!file!"
:: this needs to separated in order to add s01 tag if no season tag present
for /l %%s in (0,1,9) do set "file=!file:series.%%s.=S0%%s!"
for /l %%e in (0,1,9) do set "file=!file:%%eof2=E0%%e!"
for /l %%e in (0,1,9) do set "file=!file:%%eof3=E0%%e!"
for /l %%e in (0,1,9) do set "file=!file:%%eof4=E0%%e!"
for /l %%e in (0,1,9) do set "file=!file:%%eof5=E0%%e!"
for /l %%e in (0,1,9) do set "file=!file:%%eof6=E0%%e!"
for /l %%e in (0,1,9) do set "file=!file:%%eof7=E0%%e!"
for /l %%e in (0,1,9) do set "file=!file:%%eof8=E0%%e!"
for /l %%e in (0,1,9) do set "file=!file:%%eof9=E0%%e!"
:: if file has changed but no season tag present add s01
if not "%file%"=="%original%" echo "%file%" | find /i "s0" >nul || set "file=!file:E0=S01E0!"
if not "%file%"=="%original%" ren "%~dp1%original%%~x1" "%file%%~x1" && echo validated "%original%"

:: =============================================================================================================================
::      2. EXTRAPOLATOR
:: =============================================================================================================================

:extrapolate
set "type=" & set "year=" & set "ss=" & set "ep=" & set "episode="
set "name=%file%"
echo "%name%"| find " " >nul || set "name=%name:.= %" & rem if no spaces then then safer to replace dots

:: if short do complete skip of movie/series extrapolator breakdown
echo "%~n1" | find /i "trailer" >nul && set "type=misc" && goto skipyear
echo "%~p1" | find /i "\shorts\" >nul && set "type=misc" && goto skipyear
echo "%~p1" | find /i "\movies\" >nul && set "type=film" && goto skipss
echo "%~p1" | find /i "\series\" >nul && set "type=show"

:: episode number: last tag first
FOR /L %%e IN (100,1,199) DO (
 SET "modname=!name:E%%e=!"
 IF "!modname!" neq "%name%" (
  SET "setcmd=set name=!name:E%%e=& set ep=E%%e& set type=show& rem !"
  GOTO gotep
 )
)
FOR /L %%e IN (10,1,99) DO (
 SET "modname=!name:E%%e=!"
 IF "!modname!" neq "%name%" (
  SET "setcmd=set name=!name:E%%e=& set ep=E%%e& set type=show& rem !"
  GOTO gotep
 )
 SET "modname=!name:E0%%e=!"
 IF "!modname!" neq "%name%" (
  SET "setcmd=set name=!name:E0%%e=& set ep=E0%%e& set type=show& rem !"
  GOTO gotep
 )
)

FOR /L %%e IN (0,1,9) DO (
 SET "modname=!name:E0%%e=!"
 IF "!modname!" neq "%name%" (
  SET "setcmd=set name=!name:E0%%e=& set ep=E0%%e& set type=show& rem !"
  GOTO gotep
 )
 SET "modname=!name:E00%%e=!"
 IF "!modname!" neq "%name%" (
  SET "setcmd=set name=!name:E00%%e=& set ep=E00%%e& set type=show& rem !"
  GOTO gotep
 )
 SET "modname=!name:%%eof=!"
 IF "!modname!" neq "%name%" (
  SET "setcmd=set name=!name:%%eof=& set ep=E0%%e& set type=show& rem !"
  GOTO gotep
 )
 SET "modname=!name:x0%%e=!" 
 IF "!modname!" neq "%name%" (
  SET "setcmd=set name=!name:x0%%e=& set ep=E0%%e& set type=show& rem !"
  GOTO gotep
 )
)

GOTO skipep
:gotep
%setcmd%
:skipep

:: season number: second to last tag second
FOR /L %%e IN (0,1,9) DO (
 SET "modname=!name:S0%%e=!"
 IF "!modname!" neq "%name%" (
  SET "setcmd=set name=!name:S0%%e=& set ss=S0%%e& set type=show& rem !"
  GOTO gotss
 )
)
FOR /L %%e IN (10,1,99) DO (
 SET "modname=!name:S%%e=!"
 IF "!modname!" neq "%name%" (
  SET "setcmd=set name=!name:S%%e=& set ss=S%%e& set type=show& rem !"
  GOTO gotss
 )
)
FOR /L %%e IN (0,1,9) DO (
 SET "modname=!name:series.%%e=!"
 IF "!modname!" neq "%name%" (
  SET "setcmd=set name=!name:series.%%e=& set ss=S0%%e& set type=show& rem !"
  GOTO gotss
 )
)

GOTO skipss
:gotss
%setcmd%
:skipss

if defined ep if not defined ss set ss=S01
set "episode=%ss%%ep%"

:: year number: first tag last (first with brackets so not to confuse with imdb tag)
FOR /L %%e IN (1960,1,2020) DO (
 SET "modname=!name:(%%e)=!"
 IF "!modname!" neq "%name%" (
  SET "setcmd=set name=!name:(%%e)=& set year=%%e& if not defined type set type=film& rem !"
  GOTO gotyear
 )
)
FOR /L %%e IN (1960,1,2020) DO (
 SET "modname=!name:%%e=!"
 IF "!modname!" neq "%name%" (
  SET "setcmd=set name=!name:%%e=& set year=%%e& if not defined type set type=film& rem !"
  GOTO gotyear
 )
)
GOTO skipyear
:gotyear
%setcmd%
:skipyear

if not defined type set type=misc

:: other trimming for misc etc
set name=%name: - copy=&rem %
set name=%name: (1)=&rem %
set name=%name: (2)=&rem %
set name=%name: (3)=&rem %
set name=%name: [1]=&rem %
set name=%name: [2]=&rem %
set name=%name:360p=&rem %
set name=%name:480p=&rem %
set name=%name:720p=&rem %
set name=%name:1080p=&rem %
set name=%name:2160p=&rem %

:: changes for general use
set "name=%name: - = %"
set "name=%name:  = %"

:: trim last useless letter from name
set "name=%name%endtrimmer"
set "name=%name:(endtrimmer=endtrimmer%"
set "name=%name:[endtrimmer=endtrimmer%"
set "name=%name:.endtrimmer=endtrimmer%"
set "name=%name:-endtrimmer=endtrimmer%"
set "name=%name: endtrimmer=endtrimmer%"
set "name=%name: endtrimmer=%"
set "name=%name:_endtrimmer=%"
set "name=%name:endtrimmer=%"

:: set strings
if "%type%"=="misc" set "strict=%name: =?%"
if "%type%"=="film" if defined year set "strict=%name: =?%?(%year%)"
:: caution: this allows movie to be renamed without year tag
:: if "%type%"=="film" if not defined year set "strict=%name: =?%"
if "%type%"=="show" if defined year set "strict=%name: =?%?(%year%)?%episode%"
if "%type%"=="show" if not defined year set "strict=%name: =?%?%episode%"
if "%type%"=="show" if defined year set "loose=%name: =?%?(%year%)?s"
if "%type%"=="show" if not defined year set "loose=%name: =?%?s"

FOR %%a IN (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) DO SET "name=!name:%%a=%%a!"
endlocal & set "full=%~dp1%file%%~x1" & set "file=%file%%~x1" & set "name=%name%" & set "type=%type%" & set "year=%year%" & set "episode=%ss%%ep%" & set "strict=%strict%" & set "loose=%loose%"

:: declare (disable never delete)
echo extrapolated %type% "%strict:?= %"

:: =============================================================================================================================
::      3. FILEBOT MODERATOR
:: =============================================================================================================================

:: if rename not needed exit
if "%type%"=="misc" exit /b
if "%~2"=="-norename" exit /b

:: if already renamed we are done here
echo "%file%" | find /i " tt" >nul && exit /b

:: prep fake temp file
set tempdir=%temp%\%date:~3,2%%date:~6,2%%date:~11,2%%time:~1,1%%time:~3,2%%time:~6,2%%time:~9,2%
mkdir "%tempdir%" && copy /y nul "%tempdir%\%file%" >nul

:: variables (to shorten lines)
if "%type%"=="film" set cf=--db TheMovieDb --format "{n} ({y}) {director} {genres} r{rating} {vf} {vc} {ac} {imdbid}"
if "%type%"=="show" set cf=--db TheTVDb --format "{n} {s00e00} {t} {vf} {vc} {ac}-mallSanta"

:: rename fake temp file
filebot -rename "%tempdir%\%file%" --q "%name% %year%" %cf% >nul 2>nul

:: new name into variable
for /r "%tempdir%" %%i in (*) do set "new=%%~nxi"

:: declare failure
if "%file%"=="%new%" echo failed, reason: && filebot -rename "%tempdir%\%file%" --log warning --q "%name% %year%" %cf% & exit /b

:: check all strings against renamed orphan fake file and if successful rename 4real
for /f "delims=" %%v in ('where "%tempdir%:%strict%*" 2^>nul') do goto 4real
for /f "delims=" %%v in ('where "%tempdir%:%strict:s?='s?%*" 2^>nul') do goto 4real
for /f "delims=" %%v in ('where "%tempdir%:%strict:?-?=?%*" 2^>nul') do goto 4real

:: declare failure and confirm override
echo.
echo file "%file%" was renamed
echo to a "%new%", which was unexpected,
:: try the interactive command prompt mode in filebot?
choice /t 20 /c yn /n /d n /m "override and approve this rename? [Y]es or [N]o: "
if "%errorlevel%"=="1" goto 4real
exit /b

:4real
filebot -rename "%~dp1%file%" --q "%name% %year%" %cf% >nul 2>nul
if not exist "%~dp1%file%" echo successfully renamed "%file%"

:: validate the new file (maybe just send to validate with a -norename? takes longer but clearer code
set "original=%file%"
set "file=%file:!=%"
set "file=%file:#=%"
set "file=%file: _ = - %"
set "file=%file:’='%"
set "file=%file:“='%"
set "file=%file:”='%"
set "file=%file:_= %"
set "file=%file:—=-%"
set "file=%file:  = %"
set "file=%file:  = %"
set "file=%file:&=and%"
if not "%file%"=="%original%" ren "%~1" "%file%" && echo validated "%original%"
setlocal enabledelayedexpansion
set "original=!file!"
set "file=!file:%%= percent!"
if not "%file%"=="%original%" ren "%~dp1%original%%~x1" "%file%" && echo validated "%original%"
endlocal
exit /b

它(1.)从文件名中删除有问题的字符(2.)从文件名外推视频nameyear,其他变量,然后(3.)进行监督filebot改名。 setlocalendlocal位看起来不错。可能是问题是从另一个脚本继承的吗?

2 个答案:

答案 0 :(得分:3)

您已在批处理脚本setlocal EnableDelayedExpansion中的 ECHO 行之上的某处namer启用了延迟环境变量扩展。

因此,感叹号不会被进一步解释为文字字符,但随着变量引用的开始/结束扩展延迟。

我们需要namer批处理文件的批处理代码来帮助您解决此问题。

看起来该行用于检查文件是否包含.tmp,即文件扩展名为.tmp,如果是这种情况,请忽略该文件。

我建议更改您的第一个批处理文件

for %%v in (*) do call namer "%%v"

for %%I in (*) do if /I not "%%~xI" == ".tmp" call "%~dp0namer.cmd" "%%I"

然后.tmp批处理文件根本不处理文件扩展名为namer的文件。

在命令提示符窗口set /?中运行,以获取有关延迟扩展的更多信息,并for /?获取有关%~xI(文件的文件扩展名)的帮助以及if /?的帮助在命令 IF call /?上获取有关%~dp0的帮助。

也可以在namer.cmd中使用:

if /I "%~x1" == ".tmp" goto :EOF

如果第一个参数的文件扩展名为namer.cmd(比较不区分大小写),则退出批处理文件.tmp的处理。对于此比较,是否启用延迟扩展无关紧要。另见Where does GOTO :EOF return to?

上的答案

如果.tmp不是文件的文件扩展名,但只是文件名中的某个位置,则可以使用带字符串替换的 IF

批处理文件namer.cmd的示例。

set "FileName=%~nx1"
if not "%FileName:.tmp=%" == "%FileName%" goto :EOF

第一行指定带扩展名的文件名,但没有环境变量FileName的路径。

第二行比较区分大小写的文件名字符串,其中所有出现的.tmp都不区分大小写,而空字符串的文件名字符串根本没有修改。如果文件名字符串确实包含.tmp 1次或更多次,则两个比较的字符串不相等,从而导致批处理文件的退出处理。

换句话说, IF 条件检查分配给环境变量的字符串是否包含:=之间指定的字符串不区分大小写。

这类似于在 C 中使用

#include <string.h>

int main(int argc, char *argv[])
{
    if(argc > 1)
    {
        /* Does first argument contain the string ".tmp"? */
        if(strstr(argv[1],".tmp") != NULL) return 1;
    }
    return 0;
}

函数strstr区分大小写。

答案 1 :(得分:1)

这是一种可以在不使用转义字符的情况下使用delayedexpansion的方法。

@echo off
setlocal disabledelayedexpansion
set myfile="10 Products You’ll Never Buy Again Knowing How They Are Made!.mp4"
echo %DB_password%
setlocal enabledelayedexpansion
echo !myfile!