2016-10-28 52 views
1

在我的代码中,我只搜索文件夹和所有子文件夹中的文件。当子文件夹的名称有一个空白(空格)之间的这个子文件夹也被识别为文件。这是不正确的行为。参数/a-d在这里没有帮助。为什么在执行批处理脚本时将空格识别为文件的子文件夹?

@echo on 
Setlocal EnableDelayedExpansion 

set "input=C:\Users\NekhayenkoO\test\"** 
set "output=C:\Users\NekhayenkoO\outputxml\"** 

set string1=Well-Formed and valid 
set string2=Well-Formed, but not valid 
set string3=Not well-formed 
set /a loop=0 
set /a loop1=0 
set /a loop2=0 
set /a loop3=0 

for /f %%a in ('dir /b /a-d /s %input%') do (
    CALL jhove -m PDF-hul -h xml -o %output%\%%~na.xml %%a 
    if !ERRORLEVEL! EQU 0 (echo Errorlevel equals !errorlevel!) 
    if !ERRORLEVEL! GEQ 1 (Errorlevel equals !errorlevel!) 
    set /a loop3+=1 
) 

脚本对目录C:\Users\NekhayenkoO\jhove-beta运行输出:

Setlocal EnableDelayedExpansion 
set "input=C:\Users\NekhayenkoO\test\"** 
set "output=C:\Users\NekhayenkoO\outputxml\"** 
set string1=Well-Formed and valid 
set string2=Well-Formed, but not valid 
set string3=Not well-formed 
set /a loop=0 
set /a loop1=0 
set /a loop2=0 
set /a loop3=0 
for /F %a in ('dir /b /a-d /s "C:\Users\NekhayenkoO\test\"') do (
echo Verarbeite %~na 
CALL jhove -m PDF-hul -h xml -o "C:\Users\NekhayenkoO\outputxml\\%~na.xml" "%a" 
if !ERRORLEVEL! EQU 0 (echo Errorlevel equals !errorlevel!) 
if !ERRORLEVEL! GEQ 1 (Errorlevel equals !errorlevel!) 
set /a loop3+=1 
) 

(
echo Verarbeite 757419577 
CALL jhove -m PDF-hul -h xml -o "C:\Users\NekhayenkoO\outputxml\\757419577.xml" "C:\Users\NekhayenkoO\test\757419577.pdf" 
if !ERRORLEVEL! EQU 0 (echo Errorlevel equals !errorlevel!) 
if !ERRORLEVEL! GEQ 1 (Errorlevel equals !errorlevel!) 
set /a loop3+=1 
) 
Verarbeite 757419577 
Errorlevel equals 0 
Verarbeite GBV58575165X 
Errorlevel equals 0 
Verarbeite GBV85882115X 
java.lang.ClassCastException: edu.harvard.hul.ois.jhove.module.pdf.PdfSimpleObject cannot be cast to edu.harvard.hul.ois.jhove.module.pdf.PdfDictiona 
     at edu.harvard.hul.ois.jhove.module.PdfModule.readDocCatalogDict(PdfModule.java:1344) 
     at edu.harvard.hul.ois.jhove.module.PdfModule.parse(PdfModule.java:521) 
     at edu.harvard.hul.ois.jhove.JhoveBase.processFile(JhoveBase.java:803) 
     at edu.harvard.hul.ois.jhove.JhoveBase.process(JhoveBase.java:588) 
     at edu.harvard.hul.ois.jhove.JhoveBase.dispatch(JhoveBase.java:455) 
     at Jhove.main(Jhove.java:292) 
Errorlevel equals 0 
Verarbeite GBV858852357 
Errorlevel equals 0 
Verarbeite nicht_valide_PDF 
Errorlevel equals 0 
Verarbeite not_Wellformed_intern 
Errorlevel equals 0 
Verarbeite pp1788_text 
Errorlevel equals 0 
Verarbeite Rosetta_Testdatei 
Errorlevel equals 0 
Verarbeite script 
Errorlevel equals 0 
Verarbeite java 
Errorlevel equals 0 
Verarbeite java 
Errorlevel equals 0 
Verarbeite java 
Errorlevel equals 0 
Verarbeite java 
Errorlevel equals 0 
Verarbeite GBV58525785X 
Errorlevel equals 0 
Verarbeite GBV58574517X 
Errorlevel equals 0 
Drücken Sie eine beliebige Taste . . . 
+2

当有路径或文件名空格,使用引号周围:'... in('dir/b/a -d/s“%input%”')do ...'和'CALL jhove -m PDF-hul -h xml -o“%output%\ %%〜na.xml”“%% a”' – Stephan

+0

@斯蒂芬我已经尝试过了,但结果相同 –

+0

@OlegNekhayenko,我觉得很难相信。我很想看到脚本的执行情况。保持回应,并用该信息更新您的问题。 – Squashman

回答

1

什么是jhove?

Oleg Nekhayenko,你问在最后的日子几个jhove相关的问题,但你总是忘了解释什么jhove是要知道你的所有问题是非常重要的。

所以我搜索万维网为jhove,发现很快主页
JHOVE | JSTOR/Harvard Object Validation Environment,快速阅读其documentationcommand-line interface描述,最后下载也jhove-1_11.zipJHOVE SourceForge项目页面。

这一切都被我做找出jhove是使用shell脚本jhove在Linux上执行,或许也可以在Mac和Windows上的批处理文件jhove.bat为了更容易被用户使用Java应用程序。

你可以救自己和您的问题所有的读者很多的时间,如果你会在你的代码片段已经写jhove.bat,而不是只jhove或者任何地方至少提到jhove是一个批处理文件。

分配值/字符串变量

我建议先读这两行上
Why is no string output with 'echo %var%' after using 'set var = text' on command line?
的答案,接下来看看环境:

set "input=C:\Users\NekhayenkoO\test\"** 
set "output=C:\Users\NekhayenkoO\outputxml\"** 

我不知道为什么两个星号在这两条命令行的末尾。但是,这并不重要,因为在将两个路径分配给两个环境变量时,两个星号都会被忽略。

这可以在批处理文件的发布输出被视为有上线没有星号输出:

for /F %a in ('dir /b /a-d /s "C:\Users\NekhayenkoO\test\"') do (

CALL jhove -m PDF-hul -h xml -o "C:\Users\NekhayenkoO\outputxml\\757419577.xml" "C:\Users\NekhayenkoO\test\757419577.pdf" 

没有星号的任何地方。所以环境变量inputoutput显然没有星号,最终在这里甚至是好的。

在双引号封闭目录和文件名

在命令提示符窗口中运行cmd /?帮助输出解释了最后帮助页面上的最后一段上的目录或文件名双引号字符周围必须使用完整的目录/文件名称。

空格字符是命令行上的字符串分隔字符,因此带空格的目录或文件名必须始终用双引号括起来。在Windows

预定义的环境变量打开命令提示窗口并运行set结果在用于当前用户帐户中定义的所有的环境变量的输出,包括PATHPATHEXT为还USERNAMEUSERPROFILE

维基百科有关Windows Environment Variables的文章解释了Windows预定义的环境变量。建议在批处理文件中使用它们。

在Windows

的应用程序和脚本执行如果在命令提示符窗口或在批处理文件中指定的只是一个应用程序或脚本没有文件扩展名,没有路径的文件名,在Windows命令解释器搜索首先在当前目录中,然后在环境变量PATH的所有目录中对于具有在环境变量PATHEXT中列出的文件扩展名的指定名称的文件。在这种情况下,Windows命令解释程序正在搜索jhove.*

环境变量PATHPATHEXT的值可以看到打开命令提示窗口和运行在该窗口set path这导致开始与不区分大小写的解释字符串PATH与它们的当前值的所有的环境变量的输出。

要知道的是,当Windows命令解释程序搜索jhove.*时,NTFS文件系统返回匹配此搜索模式的文件名称按字母顺序排序。因此,如果当前目录或PATH中列出的任何目录都有例如jhove.batjhove.exe,则NTFS文件系统首先返回jhove.bat。此批处理文件由Windows命令解释程序使用,因为文件扩展名BAT默认在PATHEXT中列出。

但是,如果具有jhove.*文件的驱动器的文件系统是FAT,FAT32或ExFat,则文件系统按照存储在文件分配表中的顺序返回与搜索模式匹配的文件名,因此未排序。因此,如果某个目录包含jhove.batjhove.exe在具有任何FAT文件系统的驱动器上,则无法预知哪个文件由Windows命令解释程序在批处理文件中指定jhove执行。

因此,总是建议使用文件名称指定应用程序或脚本,并至少使用文件扩展名。如果可能的话,还应指定要运行的应用程序的整个路径或要调用的脚本。

Windows命令解释程序不需要通过指定具有文件扩展名和完整路径的应用程序或脚本文件的名称进行搜索。

参见回答Where is "START" searching for executables?

调用一个批处理文件与由线运行由Windows命令解释行解释应用

批处理文件是一个脚本(文本文件),从而命令块开始(并以与匹配)结尾的方式解释为像在一行上定义的子例程。

应用程序是一个可执行文件(二进制文件),用于针对特定处理器或处理器系列的编译器进行编译,因此在执行时不需要再解释。它包含处理器指令(机器码)。

为什么命令呼叫必须用于运行从一个批处理文件中另一个批处理文件进行详细的答案上

解释了这个原因知道什么是jhove是非常重要的。这是一个批处理文件,因此必须调用命令呼叫,回答了问题How to process 2 for loops after each other in batch?

有关命令呼叫帮助打开命令提示符窗口,然后运行call /?。输出帮助还解释了哪些占位符存在以引用批处理文件的参数,其中参数0是批处理文件的名称。

哪些命令行包含jhove.bat?

对于从另一个批处理文件调用批处理文件时发生的意外行为,重要的是要知道调用的批处理文件的代码,因为错误可能在调用批处理文件的代码中。

jhove.bat代码存储在jhove-1_11.zip没有指令评论:

@ECHO OFF 
SET JHOVE_HOME=%~dp0 

SET EXTRA_JARS= 

REM NOTE: Nothing below this line should be edited 
REM ######################################################################### 


SET CP=%JHOVE_HOME%\bin\JhoveApp.jar 
IF "%EXTRA_JARS%"=="" GOTO FI 
    SET CP=%CP%:%EXTRA_JARS 
:FI 

REM Retrieve a copy of all command line arguments to pass to the application 

SET ARGS= 
:WHILE 
IF %1x==x GOTO LOOP 
    SET ARGS=%ARGS% %1 
    SHIFT 
    GOTO WHILE 
:LOOP 


REM Set the CLASSPATH and invoke the Java loader 
java -classpath %CP% Jhove %ARGS% 

好了,这是以下原因不好写批处理代码:

  1. 命令SETLOCALendlocal不在批处理文件中用于控制此批处理文件使用的变量的生存时间。有关更多详细信息,请参见change directory command cd ..not working in batch file after npm install的答案。 npm.bat也是一个不好的编码批处理文件,如jhove.bat,因为它结果。

  2. 命令行SET JHOVE_HOME=%~dp0定义环境变量JHOVE_HOME,驱动器和存储位置的路径为jhove.bat。由%~dp0返回的路径始终以反斜杠结尾。如果jhove*.zip被提取到一个具有一个或多个完整路径空间的目录中,则必须注意最后使用JHOVE_HOME将最后一个字符串括在双引号中。

    命令行SET CP=%JHOVE_HOME%\bin\JhoveApp.jar通过将批处理文件jhove.bat的路径连接到Java程序包的固定路径和名称来定义环境变量CP。这已经是一个小错误,因为%~dp0是一个始终以一个反斜杠和一个以反斜杠开始的串联结尾的路径。所以最终在Java包文件的路径中有两个反斜杠。但是Windows内核在路径中处理这个错误,因此它并不重要。

    环境变量CP未经修改而引用,没有EXTRA_JARS,最终由用户在命令行java -classpath %CP% Jhove %ARGS%上定义。如果jhove*.zip确实被用户提取到具有一个或多个完整路径空间的目录中,则错误指定为%CP%,而不包含在导致意外行为的双引号中。

  3. 在命令行SET CP=%CP%:%EXTRA_JARS末尾缺少百分号。

  4. jhove.bat笔者不知道%*显然任何事情上最后一个命令行而不是%ARGS%的使用使得WHILE以上循环完全无用。

jhove.bat好多是:

@echo off 
setlocal EnableExtensions 
set "JHOVE_HOME=%~dp0" 

set "EXTRA_JARS=" 

REM NOTE: Nothing below this line should be edited 
REM ######################################################################### 

set "CP=%JHOVE_HOME%bin\JhoveApp.jar" 
if not "%EXTRA_JARS%"=="" set "CP=%CP%:%EXTRA_JARS%" 

rem Set the CLASSPATH and invoke the Java loader 
java.exe -classpath "%CP%" Jhove %* 
endlocal 

可执行java.exe必须通过由Windows命令解释器环境变量PATH被发现。

用于使用

最终批次码

我建议使用以下代码中的jhove.bat情况下,这任务不应该被修饰以上述工作的代码:

@echo off 
setlocal EnableExtensions 
set "InputFolder=%USERPROFILE%\test" 
set "OutputFolder=%USERPROFILE%\outputxml" 

echo Searching for bin\JhoveApp.jar in: 
echo. 
set "SearchPath=%CD%;%PATH%" 
set "SearchPath=%SearchPath:)=^)%" 
for /F "delims=" %%I in ('echo %SearchPath:;=^&ECHO %') do (
    echo %%I 
    if exist "%%~I\bin\JhoveApp.jar" (
     set "JHOVE_HOME=%%~I" 
     goto RunJHOVE 
    ) 
) 
echo. 
echo Error reported by %~f0: 
echo. 
echo Could not find bin\JhoveApp.jar in current directory and folders of PATH. 
echo. 
endlocal 
pause 
goto :EOF 

:RunJHOVE 
if "%JHOVE_HOME:~-1%" == "\" (
    set "CP=%JHOVE_HOME%bin\JhoveApp.jar" 
) else (
    set "CP=%JHOVE_HOME%\bin\JhoveApp.jar" 
) 
echo. 
echo Using %CP% 

md "%OutputFolder%" 2>nul 

rem for /F %%I in ('dir /A-D /B /S "%InputFolder%\*" 2^>nul') do (
rem  java.exe -classpath "%CP%" Jhove -m PDF-hul -h xml -o "%OutputFolder%\%%~nI.xml" "%%I" 
rem) 

for /R "%InputFolder%" %%I in (*) do (
    java.exe -classpath "%CP%" Jhove -m PDF-hul -h xml -o "%OutputFolder%\%%~nI.xml" "%%I" 
) 

endlocal 

输入和输出文件夹路径是使用预定义的环境变量USERPROFILE在末尾没有反斜线定义,没有星号。

通过Magoo在他的Find the path used by the command line when calling an executable答案写一个稍微修改后的代码被用于查找的JHOVE Java包。批处理文件将打印正在搜索的文件夹,以防文件无法找到,从而导致出现错误消息并暂停批量处理,直到用户按下任何键。

创建类路径变量CP是考虑到文件夹路径是否以反斜杠结尾。 PATH中的文件夹路径应该在末尾没有反斜线定义,但总是有安装程序将文件夹路径添加到PATH不是100%正确。但是,Windows内核处理这种情况时,路径中的任何位置的结果是否为\\都无关紧要。这就是为什么if exist "%%~I\bin\JhoveApp.jar"也始终工作的原因,虽然此文件存在测试也可以通过路径中的两个反斜杠完成,具体取决于PATH中的文件夹路径。

接下来,输出文件夹在没有先检查文件夹是否已存在的情况下创建,也不检查文件夹创建是否成功。

批处理代码包含两个解决方案,用于在输入文件夹路径中递归找到的每个文件上运行jhove。第一个被注释掉。这对于隐藏和系统文件也有好处。第二种解决方案不适用于隐藏文件和系统文件,但这在这里很可能不是必需的。第二种解决方案因此是首选。

为了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读为每个命令显示的所有帮助页面。

  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • md /?
  • pause /?
  • set /?
  • setlocal /?

而且也可以参考微软的文章:

相关问题