有没有办法计算文件夹中的文件数量,然后在超过限制(为了效率)时停止,例如 100?
我不是程序员,我相信这与循环和控制迭代有关。我尝试了一些不同的命令,但我不明白。预先感谢:)
背景故事:我有一个交互式批处理文件,它递归地列出文件夹中的文件。如果在列出文件之前有大量文件,我希望能够警告用户。我找到了一个计算文件数量的命令,catch-22 计算文件所需的时间可能与列出文件所需的时间一样长;这里涵盖了两者(计数及其效率): 高效统计目录和子文件夹中具有特定名称的文件
文件列表交互式脚本(如果对上下文有帮助):
REM https://support.microsoft.com/en-us/help/196158/how-to-create-a-text-file-list-of-the-contents-of-a-folder
REM this is a comment line, technically called a REM(ark) line
REM @echo off tells command-prompt not to show commands & directory location (what you normally see when opening cmd), the @ symbol says to not show that command itself. We clear the screen (cls) so it doesn't show THIS remark text or any errors about being run from a UNC location. The two && says that if the 1st command is successful do the 2nd one
REM %1 is a placeholder/variable for the filename of whatever is dropped-on the batch. If we had just put echo %1 & no file was specified it would be like putting echo by itself turning echo back on. IF checks whether the variable is blank/not-given & does a blank line if so; ELSE gets processed if variable wasn't blank (display the file path+name in our situation). The brackets are needed if there is a space in the file path/name. The empty brackets indicate a blank string (similar to ""). The parenthesis tells IF to process only things inside it, without it the program will think you want to run "echo. ELSE echo %1", basically echo the rest of the line
REM %~dp0 is the location of THIS batch file (%0=file path including the filename, dp tells it to cut that out [DrivePath only]), %1 is the variable holding the filename & path
@echo off && cls
echo ------------------------------------------------------------------------------
echo Directory contents I will list in Notepad:
IF [%1]==[] (echo [%~dp0]) ELSE (echo [%1])
echo.
echo You can choose another location by dragging it onto this batch file or copying this batch file to it
echo #4 is the only way to get JUST filenames. Sadly DIR command can't show just filenames AND date else it has headers and summary, try #3 for that
echo ------------------------------------------------------------------------------
REM cmd/batch files do not support UNC paths (\\acme.com\SharedFolder) natively-kb156276. PUSHD is the workaround, it maps UNC to a drive letter, then CHANGES-MOVES to that path, POPD reverts it (removes network drive)-kb317379
IF [%1]==[] (pushd %~dp0) ELSE (pushd %1)
echo.
REM declare then fill variable to file path we will store output; %temp is SYSTEM variable going to C:\Users\UserWhoRanScript\AppData\Local\Temp; parenthesis in case it has a space in path which causes errors
set ListFileLog="%temp%\FileListing.txt"
REM CHOICE prompts users; /C list of choices; /M message before prompt
CHOICE /C 123456 /M "Choose what to list: 1)All files; 2)All files-newest first (no folder dates); 3)All files-all dates (Create+Modify); 4)All files-no date or sizes; 5)Executables/compressed (exe, msi, zip, 7z, rar); 6)Media files"
REM IF ERRRORLEVEL by itself has a weird oddity so this format checks it exactly as user enters then jumps to that section of the script
IF "%ERRORLEVEL%" == "1" GOTO ListAll
IF "%ERRORLEVEL%" == "2" GOTO ListAllNewestFirst
IF "%ERRORLEVEL%" == "3" GOTO ListAll-EveryDate
IF "%ERRORLEVEL%" == "4" GOTO ListAllNoDatesSizes
IF "%ERRORLEVEL%" == "5" GOTO ListExe
IF "%ERRORLEVEL%" == "6" GOTO ListMedia
:ListAll
REM S=subdirectory files (recursive) we then redirect > that output to our text file so it stays open for user when cmd window closes. > wipes logfile contents whereas >> appends to existing logfile contents
dir /s > %ListFileLog%
GOTO ExitProc
:ListAllNewestFirst
REM /a attributes -d means don't show directories (doesn't show folder modify date or the period(.) folders); /o order by [d]ate - is to reverse so newest first; /t time-date to show ([c]reation, last [a]ccess, last [w]ritten)
dir /a:-d /o:-d /s > %ListFileLog%
GOTO ExitProc
:ListAll-EveryDate
REM shorthand: powershell ls^|fl
REM there is no way to show creation, modify, and access dates with cmd dir so using powershell. ^carat is because cmd will interpret that as you giving another command so fails
powershell.exe Get-ChildItem -Recurse ^| Select-Object FullName,CreationTime,LastWriteTime,LastAccessTime > %ListFileLog%
GOTO ExitProc
:ListAllNoDatesSizes
REM B=bare no dates or file sizes
dir /s /b > %ListFileLog%
GOTO ExitProc
:ListExe
REM show only files with these extensions, S and B switches/parameters detailed above
dir /s /b *.exe *.msi *.zip *.7z *.rar > %ListFileLog%
GOTO ExitProc
:ListMedia
dir /s /b *.mp3 *.wma *.aac *.m4a *.wav *.mpg *.mp4 *.avi > %ListFileLog%
GOTO ExitProc
:ExitProc
popd && cls
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !!DONE!! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo.
echo You should see output in Notepad, close Notepad ^& this window will close with it
start /w notepad %ListFileLog%
del %ListFileLog%
exit
如果您想将计数限制为 100,然后要求用户继续,这很简单。将此视为一种选择。 (多条 REM 线帮助解释发生了什么)
:PreCountDir [Strings to search, separated by space]
REM setlocal enabledelayedexpansion saves a little headache with
REM trying to manipulate/read variables in a for loop so there is
REM less work involved thus making it cleaner / easier to read.
REM Note - the "%" for variable designations are changed to "!" -
REM This tells the CMD interpreter while using enabledelayedexpansion
REM to expand this variable now, and confirm the value it contains
REM at the time of access. For every setlocal you should also use an
REM endlocal if you do are setting it at a module level vs globally.
REM %~1 takes the string specified and strips any wrapping quotes so
REM it doesn't break the 'Dir' command.
setlocal enabledelayedexpansion
REM "Undefines" preCount variable (makes it "nothing")
set "preCount="
REM For Loop iterates across the output of the Dir command - note -
REM it's most accurate to keep /b and /s since all options are
REM recursing in the other routines and you do not have to stress
REM about the extra "fluff" from the standard Dir command.
REM Sending stdOut to nul, as well as stdErr to keep output clean.
REM (stdErr to nul = 2^>nul)
For /f "Delims" %%D in ('Dir /s /b %~1 ^>nul 2^>nul') do (
REM incrementing preCount by 1 per file in the output
set /a "preCount+=1"
if "!preCount!" GEQ "100" (
REM Prompting user whether to continue or not.
Choice /c 12 /M "The count of files for this directory so far is at or higher than 100. Do you wish to continue? [1. Yes] [2. No]
If "!Errorlevel!"=="1" endlocal && Goto :EOF
If "!Errorlevel!"=="2" Exit
)
)
Goto :EOF
然后,在您想要确认的每个例程中,您只需将搜索字符串作为参数提供给
PreCountDir
例程即可。您可以将 :PreCountDir 放置在文件中的任何位置。
REM See the updated Routines with the PreCountDir call line
:ListAll
REM S=subdirectory files (recursive) we then redirect > that output to our text file so it stays open for user when cmd window closes. > wipes logfile contents whereas >> appends to existing logfile contents
REM No args since the search below doesn't care.
Call :PreCountDir ""
dir /s > %ListFileLog%
GOTO ExitProc
:ListAllNewestFirst
REM /a attributes -d means don't show directories (doesn't show folder modify date or the period(.) folders); /o order by [d]ate - is to reverse so newest first; /t time-date to show ([c]reation, last [a]ccess, last [w]ritten)
REM passing the check to only look for non-directories to the PreCountDir routine
REM (/a:-d) - '/o:-d' is for date specifics which don't matter on a count if no
Call :PreCountDir "/a:-d"
dir /a:-d /o:-d /s > %ListFileLog%
GOTO ExitProc
:ListAll-EveryDate
REM Calling PreCountDir with no arguments since we don't care about file filtering and all files will be accessed with the Powershell command.
Call :PreCountDir ""
REM shorthand: powershell ls^|fl
REM there is no way to show creation, modify, and access dates with cmd dir so using powershell. ^carat is because cmd will interpret that as you giving another command so fails
powershell.exe Get-ChildItem -Recurse ^| Select-Object FullName,CreationTime,LastWriteTime,LastAccessTime > %ListFileLog%
GOTO ExitProc
:ListAllNoDatesSizes
REM Calling PreCountDir with no args to match the end search.
Call :PreCountDir ""
REM B=bare no dates or file sizes
dir /s /b > %ListFileLog%
GOTO ExitProc
:ListExe
REM Calling PreCountDir to look for the same filetypes
Call :PreCountDir "*.exe *.msi *.zip *.7z *.rar"
REM show only files with these extensions, S and B switches/parameters detailed above
dir /s /b *.exe *.msi *.zip *.7z *.rar > %ListFileLog%
GOTO ExitProc
:ListMedia
REM Calling PreCountDir to search for extensions below and count:
Call :PreCountDir "*.mp3 *.wma *.aac *.m4a *.wav *.mpg *.mp4 *.avi"
dir /s /b *.mp3 *.wma *.aac *.m4a *.wav *.mpg *.mp4 *.avi > %ListFileLog%
GOTO ExitProc
REM <-----Placing :PreCountDir here----->
:PreCountDir [Strings to search, separated by space]
. . .
REM Code for PreCountDir
. . .
:ExitProc
. . .
REM Code for ExitProc
. . .
Exit