powershell 使用批处理将文件属性(至少包括Created、LastWrite、LastAccess)从一个文件复制到另一个文件

vyswwuz2  于 2023-02-04  发布在  Shell
关注(0)|答案(1)|浏览(275)

我正在尝试复制 *.mkv *. mp4视频文件的属性。我已经找到了复制文件属性的方法,但它相当慢,因为它正在调用Powershell来使用它的命令。

powershell ^(ls '!orig-file!'^).CreationTime = ^(ls '%%I'^).CreationTime
powershell ^(ls '!orig-file!'^).LastWriteTime = ^(ls '%%I'^).LastWriteTime
powershell ^(ls '!orig-file!'^).LastAccessTime = ^(ls '%%I'^).LastAccessTime
...................
%%I equals new-file for each FOR loop iteration

有没有办法在没有Powershell的情况下更快地完成这项工作?
否则,我假设只调用Powershell一次就可以在一行中复制所有3个或更多属性?我假设单独阅读每个文件属性是复制的唯一方法,但如果有更多属性要复制,我宁愿复制所有属性。
编辑:完整代码:(删除所有注解行)(批量转换视频音频从一种格式到另一种格式)

@ECHO OFF
SETlocal

SET drive="~dp0"
SET string=%CD%  

SETlocal EnableExtensions EnableDelayedExpansion
SET "drive=G:"
SET ^"Exclude-AlltheseFolders=#snapshot,output^"
SET "Convert_Audio1=Y"
SET "Convert_TO=aac"
SET "Codec1=eac3"
SET "Codec2=flac"
SET "Codec3=dts" &SET "Codec4=pcm_s24le" &SET "Codec5=aac" &SET "Codec6=ac3"
SET "KeepExtraAudio_NoOrig=Y"
SET "KeepOrigAudio=N"
SET "OverWriteFiles=N"
SET "ExtractTime=Y"
SET "time_to_start_from=00:00:10" &SET "duration_to_capture=00:00:15"
SET "TempFilePath=C:\Windows\Temp\ffmpeg-CountingScript-AllFilesInCurrentDirlist%DT%--%HH%.%MM%.%SS%.txt"

IF !ExtractTime! == Y ( SET "FFmpgextractTime= -ss !time_to_start_from! -t !duration_to_capture!")
ECHO THIS IS JMK1
IF !OverWriteFiles! == Y (SET "OverWrite=-y ") ELSE (SET "OverWrite=-n ")
IF !Convert_Audio1! == Y (
    IF !Convert_TO! == aac ( set "Convert_TO=libfdk_aac" )
    SET "FFmpgConvertStream1=-c:a:0 !Convert_TO! -b:a:0 640k -disposition:a:0 default"
    IF !KeepExtraAudio_NoOrig! == Y (
        SET "FFmpgXtraStream=-c:a copy"
    )
    IF !KeepOrigAudio! == Y (
        SET "KeepOrigAudio_ffMpg=-map 0:a:0? -c:a:0 copy"
        SET "KeepExtraAudio_NoOrig=Y"
    )
) ELSE (
    SET "ConvertCodecs=1" 
    SET "KeepOrigAudio_ffMpg=-c:a:0 copy"
    SET "KeepExtraAudio_NoOrig=Y"
)
SET "delm1=^\^>" /c:"^\^<"
SET ^"Exclude-Final=/c:"\^<!Exclude-AlltheseFolders!\^>"^"
SET ^"Exclude-Final=!Exclude-Final:,=%delm1%!^"

dir *.mkv *.mp4 /A-D-H /B /S |findstr /R %Exclude-Final% /v /i>%TempFilePath%
Echo:   These are the folders being Excluded:           "!Exclude-AlltheseFolders!"
SET "FINALCOMMAND="

SETlocal EnableExtensions DisableDelayedExpansion
SET "ProgramFolder=C:\Program Files\FFmpeg-v2020\bin"
SET "ProbeOptions=-v quiet -select_streams a:0 -show_entries "stream^^=codec_name" -of json"
SET "FilesFound=0" & SET "FilesEncoded=0" & SET "output="
for /F "delims=" %%I in (%TempFilePath%) do (
    SET "output=%drive%%%~pI%%~nxI" & SET folder=%drive%%%~pI & SET "filename=%%~nxI" & SET /A FilesFound+=1
    SETlocal EnableExtensions EnableDelayedExpansion
    IF exist "%drive%%%~pIoutput\%%~nxI" (SET "Convert_Audio1=N") ELSE SET "Convert_Audio1=Y"
    IF "!Convert_Audio1!" == "Y" (
        SET "AudioCodec=" & SET "ConvertCodecs="
        for /F "eol={ tokens=1,2 delims=,:[ ]{} " %%B in ('""%ProgramFolder%\ffprobe.exe" %ProbeOptions% "%%I""') do (
            IF "%%~B" == "codec_name" (
                IF not defined AudioCodec (
                    SET "AudioCodec=%%~C"
                )
                IF "%%~C" == "%Codec1%" (SET "ConvertCodecs=1"
            ) else IF "%%~C" == "%Codec2%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
            ) else IF "%%~C" == "%Codec3%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
            ) else IF "%%~C" == "%Codec4%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
            ) else IF "%%~C" == "%Codec5%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
            ) else IF "%%~C" == "%Codec6%" (SET "ConvertCodecs=1" & ECHO Codec is: %%~C
            )
        )
    )
)

IF !ConvertCodecs! == 1 (
    ECHO [91m==!TIME!================[0m!Codec1! [94min[0m- %%I [91m=========[0m
)

IF !ConvertCodecs! == 1 (
    IF /I "!output!" == "%%I" (
        SET "output=%~dp0output\!filename!"
        MKDIR "%~dp0output\"
    ) ELSE (
        MKDIR "%drive%%%~pI"
    )
        SET "FINALCOMMAND=ffmpeg !OverWrite!-hide_banner%FFmpgextractTime% -loglevel quiet -hwaccel auto -stats -i "%%I" -map 0:v -map_metadata 0 -movflags use_metadata_tags -map 0:a? -map 0:s:0? -c:s:0 copy -c:v copy %FFmpgXtraStream% %FFmpgConvertStream1% %KeepOrigAudio_ffMpg% "!output!" "
        ECHO this is the command1: !FINALCOMMAND!
        !FINALCOMMAND!
        ECHO [91m=====[0mCOMPLETE[91m===============[0m .
        IF not %FilesEncoded% == 0 ECHO     This one was a failure. Count Encoded so far: "%FilesEncoded%"
        IF not errorlevel 1 SET /A FilesEncoded+=1
        powershell ^(ls '!output!'^).CreationTime = ^(ls '%%I'^).CreationTime
        powershell ^(ls '!output!'^).LastWriteTime = ^(ls '%%I'^).LastWriteTime
        powershell ^(ls '!output!'^).LastAccessTime = ^(ls '%%I'^).LastAccessTime

        for /F "delims=" %%p in ("!ConvertCodecs!") do (
            ECHO THIS IS P: %%p
            ENDLOCAL
            SET /A FilesEncoded=%%p+FilesEncoded
        )

    ) ELSE ( ECHO ##NOT PROCESSING##: !TIME! - %%I ## & ECHO [91m=====--[0mFILE ALREADY EXISTS! [91m======================[0m Next File [91m===========================[0m )
    )
)

IF %FilesFound% == 1 ( SET "PluralS=" ) else SET "PluralS=s"
ECHO [91m***************************************************************************************[0m
ECHO Re-encoded %FilesEncoded% of %FilesFound% video file%PluralS%.
ECHO [91m***************************************************************************************[0m
endlocal
endlocal
endlocal
exit /b
mec1mxoz

mec1mxoz1#

以下代码使用 singlepowershell.exe调用复制指定的属性:

  • 注意gi的使用,它是Get-Item cmdlet的内置别名。
  • ls-在Windows上-(不幸的是)是Get-ChildItem cmdlet的内置别名(在这里也可以使用它,它的PowerShell惯用别名是gci);然而,这样的别名--以 other shells' / platforms的内置命令/实用程序命名的--是 * 最好避免的 * --请参阅this answer的底部部分以获得更多信息。
  • 将整个(隐含的)-Command参数包含在"..."中可以避免使用^-转义单个字符。
powershell "$target = gi '!orig-file!'; $source = gi '%%i'; 'CreationTime', 'LastWriteTime', 'LastAccessTime' | foreach { $target.$_ = $source.$_ }"

请注意,在以下情况下,上述操作仍可能失败:

  • 如果文件名恰好包含'本身;如果是,请使用\""...\""(原文如此)代替'...'
  • 有关详细信息,请参见this answer
  • 如果文件名恰好包含[];如果是,请使用gi -LiteralPath,而不仅仅是gi,这意味着gi -Path

相关问题