0

サブフォルダーのあるフォルダー内の変更された日付で設定可能な数のファイル(ファイルのみ)を並べ替えるvbsを作成し、次のように絶対パスでファイルを印刷する必要があります。

vbs:

Dim MAX
Dim Folder
MAX = 100
Folder = "C:\Test"
vbscript functions to group all files of all subfolders, and sort them by MOD date... ok
vbscript funciont to make a text file output (This i can't do it by myself)
end

テキストファイルの出力(最新の100ファイル):

c:\newest 1st file.txt
c:\subfolder1\newest 2nd file.txt
c:\subfolder7\newest 3rd file.txt
c:\subfolder2\newest 4 file.txt
c:\subfolder8\newest 5 file.txt
c:\subfolder4\newest 6 file.txt
c:\subfolder2\newest 7 file.txt
c:\newest 8 file.txt
c:\subfolder3\newest 9 file.txt
etc...

解決策がバッチで実行できるかどうかは本当に問題ではありません、私は同意します、しかし私はこれを試しました:

Dir /S /TC /O-D

そして唯一の問題は私に絶対的な道を示さないということです...

編集:ああ、そしてもちろん私は試しました:

Dir / B / S / TC / O-D

しかし、/ Bパラメーターは、前に言ったコマンドの大きな違いを意味します...

つまり:

Dir / S / TC / O-D

コマンドは、すべてのサブディレクトリ内のすべてのファイルを(一緒に)グループ化し、日付で並べ替えます。(良い!)

Dir / B / S / TC / O-D

コマンドは、フォルダーごとに処理し、各ファイルを並べ替えて表示します。(悪い!)

したがって、neswestで100個のファイルのみを並べ替える必要がある場合、および「/B」パラメーターを指定してBatchdirコマンドを使用すると、次のようになります。

出力:

(Position 1) c:\subfolder1\Newest 1st file of this folder.txt
(Position 2) c:\subfolder1\Newest 2nd fil eof this folder.txt
(Position 3) c:\subfolder1\Old file of this folder.txt
(Position 3) c:\subfolder1\Older file of this folder.txt
(Position 4) c:\subfolder1\Oldest file of this folder.txt
(Position 5) c:\subfolder2\Newest 1st file of this folder.txt
(Position 6) c:\subfolder2\Newest 2nd file of this folder.txt
(Position 7) c:\subfolder2\Old file.txt
etc ...

したがって、/ Bパラメータでdirを使用することについては何も言わないでください、私はそれが良いことを知っています:(。

再度、感謝します

4

4 に答える 4

2

これは、ネイティブ コマンドのみを使用する純粋なバッチ ソリューションです。実際にうまく機能します :-)

私は WMIC の経験があまりないので、WMIC コマンドでエスケープする必要がある追加の文字があるかどうかはわかりません。しかし、それ以外はかなり防弾だと思います。

::treeNewestFiles FileCount [RootFolder]
::
::  Searches the directory tree rooted at RootFolder and prints
::  the most recently modified files. The number of files printed
::  is limited to a maximum of FileCount. If RootFolder is not
::  specified then the root is the current directory.
::
@echo off
setlocal disableDelayedExpansion

::define base temp file name
set "tempFile=%temp%\fileDates%random%.txt"

::Loop through all folders rooted at %2 (current directory if not specified), and use
::WMIC to list last modified timestamp and full path of each file in each folder.
::The last modified timestamp is in UTC ISO 8601 format, so it sorts properly.
(
  for /r %2 %%F in (.) do (
    set "folder=%%~pnxF"
    set "drive=%%~dF"
    setlocal enableDelayedExpansion
    2>nul wmic datafile where (path='!folder:\^=\\!\\' and drive='%%~dF'^) get lastmodified, name
    endlocal
  )
)>"%tempFile%"

::Convert unicode to ansii
type "%tempFile%" >"%tempFile%2"

::Preserve only data rows
findstr "^[0-9]" "%tempFile%2" >"%tempFile%3"

::Sort the results in descending order
sort /r "%tempFile%3" >"%tempFile%4"

::Print first %1 files in results
set n=0
for /f "usebackq tokens=1*" %%A in ("%tempFile%4") do (
  echo %%B
  set /a "n+=1, 1/(%1-n)" 2>nul || goto finish
)

:finish
del "%tempFile%*"

新しい高速バージョン

私の元のコードは、ディレクトリごとに WMIC への新しい呼び出しを作成しました。各呼び出しで WMIC を初期化するには、かなりの時間がかかります。コマンドのスクリプトを作成し、WMIC を 1 回だけ呼び出すことで、実行時間を 45% 短縮しました。パフォーマンスの向上量は、ツリー内のディレクトリ数の関数です。ディレクトリの数が多いほど、この新しいバージョンが役立ちます。VBS に変換することでさらにパフォーマンスが向上することは確かですが、その努力に見合う価値はないと思います。このプロセスは現在、かなり最適化されていると思います。

::treeNewestFiles FileCount [RootFolder]
::
::  Searches the directory tree rooted at RootFolder and prints
::  the most recently modified files. The number of files printed
::  is limited to a maximum of FileCount. If RootFolder is not
::  specified then the root is the current directory.
::
@echo off
setlocal disableDelayedExpansion

::define temp folder for temp files
set "tempFolder=%temp%\fildates%random%"
md "%tempFolder%"

::define base path\name for temp files
set "tempFile=%tempFolder%\tempFile.txt"

::Loop through all folders rooted at %2 (current directory if not specified),
::and build a script of WMIC commands that will list last modified timestamps
::and full path of files for each folder. The last modified tamestamp will
::be in ISO 8601 format, so it sorts properly.
(
  echo /append:"%tempFile%1"
  for /r %2 %%F in (.) do (
    set "folder=%%~pnxF"
    set "drive=%%~dF"
    setlocal enableDelayedExpansion
    echo datafile where (path='!folder:\^=\\!\\' and drive='%%~dF'^) get lastmodified, name
    endlocal
  )
  echo quit
)>"%tempFile%"

::Execute the WMIC script
::WMIC creates a temporary file in current directory,
::so change directory 1st so it doesn't interfere with results.
pushd "%tempFolder%"
cmd /c ^<"%tempFile%" wmic ^>nul 2^>nul

::Convert unicode to ansii
type "%tempFile%1" >"%tempFile%2"

::Preserve only data rows
findstr "^[0-9]" "%tempFile%2" >"%tempFile%3"

::Sort the results in descending order
sort /r "%tempFile%3" >"%tempFile%4"

::Print first %1 files in results
set n=0
for /f "usebackq tokens=1*" %%A in ("%tempFile%4") do (
  echo %%B
  set /a "n+=1, 1/(%1-n)" 2>nul || goto finish
)

:finish
popd
rd /q /s "%tempFolder%"
于 2012-04-19T03:54:02.640 に答える
2

上記の KH1 のアドバイスに従います。バッチファイル。以下のプログラムは、ファイルの YYYYMMDDHHMM Modified Time Stamp を配列のインデックスとして使用します。このように、配列はBatch SET コマンドによって自動的にソートされたままになります。パラメータは上記の dbenham プログラムと同じです: FileCount とオプションの RootFolder。

@echo off
setlocal EnableDelayedExpansion

rem Get order of FileTimeStamp elements independent of regional settings
for /F "skip=1 tokens=2-4 delims=(-)" %%a in ('date^<NUL') do (
   set timeStampOrder=%%a %%b %%c ho mi ap
)

rem For each file in the folder given by %2 (default current one)
for /R %2 %%F in (*.*) do (
   rem Extract FileTimeStamp data (yy mm dd ho mi ap)
   for /F "tokens=1-6" %%a in ("%timeStampOrder%") do (
      for /F "tokens=1-6 delims=/-.: " %%i in ("%%~tF") do (
         set %%a=%%i
         set %%b=%%j
         set %%c=%%k
         set %%d=%%l
         set %%e=%%m
         set %%f=%%n
      )
   )
   rem Adjust hour if needed
   if !ap! equ p set /A "ho=10!ho! %% 100 + 12
   rem Create the array element with proper index
   set "file[!yy!!mm!!dd!!ho!!mi!]=%%~fF"
)

rem At this point the array is automatically sorted

rem Show the first %1 array elements
set n=0
for /F "tokens=2 delims==" %%a in ('set file[') do (
   echo %%a
   set /A n+=1
   if !n! equ %1 goto finish
)

:finish
于 2012-04-19T05:48:55.367 に答える
1

forコマンドと ~ 構文を使用して実行できます (「 」を参照for /?)。

(for /r %A in (*) do @echo %~tA %A ) | sort /r

角かっこを使用すると、単一のリダイレクト od 全体forから へのリダイレクトが可能になりsortます。中括弧がないと、 everyechoは individual にリダイレクトされるsortため、並べ替えは行われません。

編集: Ekkehard.Horner が指摘したように、上記のコードは、日付が yyyy-mm-dd 形式で印刷される地域でのみ機能します。日付が mm/dd/yyyy 形式で印刷される地域では、次のバッチ ファイルを使用できます。

@Echo Off
setlocal enabledelayedexpansion

if "%1"=="list" goto :list
%0 list | sort /r

endlocal
goto :EOF

:list
for /r %%A in (*) do (
  set t=%%~tA
  echo !t:~6,4!-!t:~0,2!-!t:~3,2! %%A
)
goto :EOF

バッチ ファイル内で括弧を使用してトリックを繰り返すことができなかったため、スクリプトはパラメーターを使用して自分自身を呼び出し、ファイルのリストを出力して出力を並べ替えます。%variable~:start-length%日付は、構文 ( を参照set /?) および遅延変数展開を使用して yyyy-mm-dd 形式に変換されます。dbenham のソリューションほど防弾ではありませんが、機能します。

于 2012-04-18T18:00:46.483 に答える
1

開始するための 3 ステップのデモ:

Option Explicit

' ADO Constants needed in this demo
Const adDBTimeStamp      =        135 ' 00000087
Const adVarWChar         =        202 ' 000000CA
Const adClipString       =          2 ' 00000002

' Globals
Dim goFS   : Set goFS = CreateObject("Scripting.FileSystemObject")
Dim gsSDir : gsSDir   = "..."

' Dispatch using comments or re-order
WScript.Quit demoTraversal()
WScript.Quit demoDirWalker()
WScript.Quit demoAdoDirWalker()

' Step00: Understanding recursive traversal
Function demoTraversal()
  walkDir00 goFS.GetFolder(gsSDir)
End Function ' demoTraversal

' Minimal recursive traversal: do something for each file in folder and
' then call same Sub for each subfolder
Sub walkDir00(oDir)
  Dim oElm
  For Each oElm In oDir.Files
      WScript.Echo oElm.DateLastModified, oElm.Path
  Next
  For Each oElm In oDir.SubFolders
      walkDir00 oElm
  Next
End Sub ' walkDir00

' Step01: Recursive traversal with Class
' Use an object to abstract the 'something' action(s) and to augment
' state (count)
Function demoDirWalker()
  Dim oDirWalker : Set oDirWalker = New cDirWalker01.init()
  walkDir01 goFS.GetFolder(gsSDir), oDirWalker
  WScript.Echo oDirWalker.Count, "files seen"
End Function ' demoTraversal

Class cDirWalker01
  Private m_nCount
  Public Function init()
    Set init    = Me
    m_nCount    = 0
  End Function ' init
  Public Sub processFile(oFile)
    ' add bool expression or function to filter
    WScript.Echo oFile.DateLastModified, oFile.Path
    m_nCount = m_nCount + 1
  End Sub ' processFile
  Public Property Get Count()
    Count = m_nCount
  End Property ' Count
End Class ' cDirWalker01

Sub walkDir01(oDir, oDirWalker)
  Dim oElm
  For Each oElm In oDir.Files
      oDirWalker.processFile oElm
  Next
  For Each oElm In oDir.SubFolders
    ' add bool expression or DirWalker.method to filter
      walkDir01 oElm, oDirWalker
  Next
End Sub ' walkDir00

' Step02: Solution (POC)
Function demoAdoDirWalker()
  Dim oDirWalker : Set oDirWalker = New cAdoDirWalker.init()
  walkDir01 goFS.GetFolder(gsSDir), oDirWalker
  oDirWalker.sort "sPath ASC, dtLM ASC"
  WScript.Echo oDirWalker.getResultString()
  oDirWalker.sort "dtLM DESC, sPath ASC"
  WScript.Echo oDirWalker.getResultString()
End Function ' demoAdoDirWalker

Class cAdoDirWalker
  Private m_oRS
  Public Function init()
    Set init  = Me
    Set m_oRS = CreateObject("ADODB.Recordset")
    m_oRS.Fields.Append "dtLM" , adDBTimeStamp
    m_oRS.Fields.Append "sPath", adVarWChar, 255
    m_oRS.Open
  End Function ' init
  Public Sub processFile(oFile)
    m_oRS.AddNew
    m_oRS.Fields("sPath").Value = oFile.Path
    m_oRS.Fields("dtLM" ).Value = oFile.DateLastModified
    m_oRS.Update
  End Sub ' add
  Public Sub sort(sWhat)
    m_oRS.sort = sWhat
  End Sub ' sort
  Public Function GetResultString()
    m_oRS.MoveFirst
    GetResultString = m_oRS.GetString(adClipString, , " | ", vbCrLf, "NULL")
  End Function ' GetResultString
End Class ' cAdoDirWalker

主なアイデアは、切断された ADO レコードセットを使用して、ファイルのコレクションをフォルダー ツリーに格納および並べ替えることです。

于 2012-04-18T13:53:09.133 に答える