2016-10-28 19 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 /?

而且也可以參考微軟的文章:

相關問題