可以复制和粘贴在Windows CMD中模拟? [英] Can copy & paste be emulated in windows CMD?

查看:81
本文介绍了可以复制和粘贴在Windows CMD中模拟?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可以在批处理脚本中将"Windows资源管理器样式"复制并复制到粘贴使用吗?

In a batch script can "Windows Explorer style" copy & paste be used?

例如

copy example.exe
some arbitrary  commands 
paste example.exe

更新:可以通过cmd完成复制到剪贴板的操作,但是

Update: copying to the clipboard can do done through cmd but

似乎只能粘贴文本,而不能使用 WinClip & 粘贴

It looks like it's not possible to paste anything but text with out third party utilities like WinClip & Paste

推荐答案

使用PowerShell可以将文件和文件夹列表复制到[Windows.Forms.Clipboard]::SetFileDropList($collection),并可以使用[Windows.Forms.Clipboard]::GetFileDropList()以及标准文件复制或流读取器进行粘贴/编写器方法.这些方法真正使用剪贴板,因此可以从控制台粘贴通过资源管理器复制的文件,反之亦然.另外,使用脚本操作剪贴板FileDropList可以使您从多个位置将文件追加到列表中-GUI界面不允许这样做.

Using PowerShell it is possible to copy a list of files and folders to [Windows.Forms.Clipboard]::SetFileDropList($collection) and to paste using [Windows.Forms.Clipboard]::GetFileDropList() along with standard file copy or stream reader / writer methods. These methods truly use the clipboard, so files copied through Explorer can be pasted from the console, and vice versa. As a bonus, using scripting to manipulate the clipboard FileDropList allows you to append files to the list from multiple locations -- something the GUI interface doesn't allow.

PowerShell脚本可以创建为Batch + PowerShell多重标记.因此,您的问题的答案是,是的,可以使用.bat脚本来做您想做的事情.

PowerShell scripts can be created as Batch + PowerShell polyglots. So the answer to your question is, yes, it is possible to do what you want with .bat scripts.

fcopy.bat:

用法:

fcopy.bat [switch] filemask [filemask [filemask [etc.]]]
fcopy.bat /?

代码:

<# : fcopy.bat -- https://stackoverflow.com/a/43924711/1683264
@echo off & setlocal

if "%~1"=="" ( goto usage ) else if "%~1"=="/?" goto usage
set args=%*

rem // kludge for PowerShell's reluctance to start in a dir containing []
set "wd=%CD%"

powershell -STA -noprofile "iex (${%~f0} | out-string)"

goto :EOF

:usage
echo Usage: %~nx0 [switch] filemask [filemask [filemask [...]]]
echo    example: %~nx0 *.jpg *.gif *.bmp
echo;
echo Switches:
echo    /L    list current contents of clipboard file droplist
echo    /C    clear clipboard
echo    /X    cut files (Without this switch, the action is copy.)
echo    /A    append files to existing clipboard file droplist
goto :EOF

: end batch / begin powershell #>

$col = new-object Collections.Specialized.StringCollection
Add-Type -AssemblyName System.Windows.Forms
$files = $()
$switches = @{}
# work around PowerShell's inability to start in a directory containing brackets
cd -PSPath $env:wd

# cmd calling PowerShell calling cmd.  Awesome.  Tokenization of arguments and
# expansion of wildcards is profoundly simpler when using a cmd.exe for loop.
$argv = @(
    cmd /c "for %I in ($env:args) do @echo(%~I"
    cmd /c "for /D %I in ($env:args) do @echo(%~I"
) -replace "([\[\]])", "```$1"

$argv | ?{$_.length -gt 3 -and (test-path $_)} | %{ $files += ,(gi -force $_).FullName }
$argv | ?{$_ -match "^[/-]\w\W*$"} | %{
    switch -wildcard ($_) {
        "?a" { $switches["append"] = $true; break }
        "?c" { $switches["clear"] = $true; break }
        "?l" { $switches["list"] = $true; break }
        "?x" { $switches["cut"] = $true; break }
        default { "Unrecognized option: $_"; exit 1 }
    }
}

if ($switches["clear"]) {
    [Windows.Forms.Clipboard]::Clear()
    "<empty>"
    exit
}

if ($switches["list"] -and [Windows.Forms.Clipboard]::ContainsFileDropList()) {
    $cut = [windows.forms.clipboard]::GetData("Preferred DropEffect").ReadByte() -eq 2
    [Windows.Forms.Clipboard]::GetFileDropList() | %{
        if ($cut) { write-host -f DarkGray $_ } else { $_ }
    }
}

if ($files.Length) {

    $data = new-object Windows.Forms.DataObject
    if ($switches["cut"]) { $action = 2 } else { $action = 5 }
    $effect = [byte[]]($action, 0, 0, 0)
    $drop = new-object IO.MemoryStream
    $drop.Write($effect, 0, $effect.Length)

    if ($switches["append"] -and [Windows.Forms.Clipboard]::ContainsFileDropList()) {
        [Windows.Forms.Clipboard]::GetFileDropList() | %{ $files += ,$_ }
    }
    $color = ("DarkGray","Gray")[!$switches["cut"]]
    $files | select -uniq | %{ write-host -f $color $col[$col.Add($_)] }

    $data.SetFileDropList($col)
    $data.SetData("Preferred DropEffect", $drop)

    [Windows.Forms.Clipboard]::Clear()
    [Windows.Forms.Clipboard]::SetDataObject($data, $true)
    $drop.Close()
}


paste.bat:

用法:

paste.bat [destination]

代码:

<# : paste.bat -- https://stackoverflow.com/a/43924711/1683264
@echo off & setlocal

set args=%*
set "wd=%CD%"

powershell -STA -noprofile "iex (${%~f0} | out-string)"

goto :EOF
: end batch / begin powershell #>

$files = @()
[uint64]$totalbytes = 0
# kludge for PowerShell's reluctance to start in a path containing []
cd -PSPath $env:wd
Add-Type -AssemblyName System.Windows.Forms

if (-not [Windows.Forms.Clipboard]::ContainsFileDropList()) { exit }
# cut = 2; copy = 5
$de = [Windows.Forms.Clipboard]::GetData("Preferred DropEffect")
if ($de) {$cut = $de.ReadByte() -eq 2} else {$cut = $false}

function newdir ([string]$dir) {
    [void](md $dir)
    write-host -nonewline "* " -f cyan
    write-host -nonewline "Created "
    write-host $dir -f white
}

if ($env:args) {
    [string[]]$argv = cmd /c "for %I in ($env:args) do @echo(%~I"
    if (test-path -PSPath $argv[0] -type Container) {
        try { cd -PSPath $argv[0] }
        catch { write-host -f red "* Unable to change directory to $($argv[0])"; exit 1 }
    } else {
        try { newdir $argv[0] }
        catch { write-host -f red "* Unable to create $($argv[0])"; exit 1 }
        cd -PSPath $argv[0]
    }
}

Add-Type @'

using System;
using System.Runtime.InteropServices;

namespace shlwapi {
    public static class dll {
        [DllImport("shlwapi.dll")]
        public static extern long StrFormatByteSize64(ulong fileSize,
            System.Text.StringBuilder buffer, int bufferSize);
    }
}
'@

function num2size ($num) {
    $sb = new-object Text.StringBuilder 16
    [void][shlwapi.dll]::StrFormatByteSize64($num, $sb, $sb.Capacity)
    $sb.ToString()
}

# returns the true drive letter, even if the supplied path contains a junction / symlink
function Resolve-Drive ([string]$path) {
    while ($path.Length -gt 3) {
        $dir = gi -force -PSPath $path
        if ($dir.Attributes -band [IO.FileAttributes]::ReparsePoint) {
            $path = $dir.Target
            if ($path.Length -eq 3) { break }
        }
        $path = (resolve-path "$path\..").Path
    }
    $path
}

function Move-File ([string]$from, [string]$to) {
    $srcdrive = Resolve-Drive $from
    $destdrive = Resolve-Drive (Convert-Path .)
    if ($srcdrive -eq $destdrive) {
        Move-Item $from $to -force
        write-host -n -f green "* "
        write-host -n -f white (gi -force -PSPath $to).Name
        write-host " moved."
    } else {
        Copy-File $from $to "Moving"
        gi -force -PSPath $from | Remove-Item -force
    }
}

# based on https://stackoverflow.com/a/13658936/1683264
function Copy-File {
    param([string]$from, [string]$to, [string]$action = "Copying")
    if (test-path -type leaf -PSPath $to) { gi -force -PSPath $to | Remove-Item -force }
    $ffile = [io.file]::OpenRead($from)
    $tofile = [io.file]::OpenWrite($to)
    $fileobj = gi -force -PSPath $tofile.Name
    $filesize = $ffile.length
    $size = num2size $filesize
    try {
        if ($filesize -ge 16*1024*1024) {
            $buffersize = 16*1024*1024
        } else { $buffersize = $filesize }
        Write-Progress `
            -Id 1 `
            -Activity "0% $action $size file" `
            -status $fileobj.Name `
            -PercentComplete 0
        $sw = [System.Diagnostics.Stopwatch]::StartNew();
        [byte[]]$buff = new-object byte[] $buffersize
        [uint64]$total = [uint64]$count = 0
        do {
            $count = $ffile.Read($buff, 0, $buff.Length)
            $tofile.Write($buff, 0, $count)
            $total += $count
            if (!$ffile.Length) {
                $pctcomp = 0
            } else {
                [int]$pctcomp = ([int]($total/$ffile.Length* 100))
            }
            [int]$secselapsed = [int]($sw.elapsedmilliseconds.ToString())/1000
            if ( $secselapsed -ne 0 ) {
                [single]$xferrate = (($total/$secselapsed)/1mb)
            } else {
                [single]$xferrate = 0.0
            }
            if ($total % 1mb -eq 0) {
                if ($pctcomp -gt 0) {
                    [int]$secsleft = ((($secselapsed/$pctcomp)* 100)-$secselapsed)
                } else {
                    [int]$secsleft = 0
                }
                Write-Progress `
                    -Id 1 `
                    -Activity ($pctcomp.ToString() + "% $action $size file @ " + `
                        "{0:n2}" -f $xferrate + " MB/s") `
                    -status $fileobj.Name `
                    -PercentComplete $pctcomp `
                    -SecondsRemaining $secsleft
            }
        } while ($count -gt 0)
        $sw.Stop()
        $sw.Reset()
    }
    finally {
        $tofile.Close()
        $ffile.Close()
        $ffile = gi -force -PSPath $from
        $fileobj.CreationTime = $ffile.CreationTime
        $fileobj.LastWriteTime = $ffile.LastWriteTime
        if ( $secselapsed -ne 0 ) {
            [string]$xferrate = "{0:n2} MB" -f (($total/$secselapsed)/1mb)
        } else {
            [string]$xferrate = num2size $fileobj.Length
        }
        write-host -nonewline "* " -f green
        write-host -nonewline $fileobj.Name -f white
        write-host (" written in $secselapsed second{0} at $xferrate/s." -f (`
            "s" * ($secselapsed -ne 1)));
    }
}

[Windows.Forms.Clipboard]::GetFileDropList() | %{
    if (test-path -PSPath $_ -Type Leaf) {
        $add = @($_.Trim(), ((Convert-Path .) + "\" + (gi -force -PSPath $_).Name))
        if ($files -notcontains $add) {
            $totalbytes += (gi -force -PSPath $_).Length
            $files += ,$add
        }
    } else {
        if (test-path -PSPath $_ -Type Container) {
            $src = (Convert-Path -PSPath $_).Trim()
            $dest = (Convert-Path .) + "\" + (gi -force -PSPath $src).Name
            if (!(test-path -PSPath $dest)) { newdir $dest }
            gci -PSPath $src -recurse -force | %{
                $dest1 = $dest + $_.FullName.Replace($src, '')
                if ((test-path -PSPath $_.FullName -Type Container) -and !(test-path -PSPath $dest1)) {
                    newdir $dest1
                }
                if (test-path -PSPath $_.FullName -Type Leaf) {
                    $add = @($_.FullName.Trim(), $dest1)
                    if ($files -notcontains $add) {
                        $totalbytes += $_.Length
                        $files += ,$add
                    }
                }
            }
        }
    }
}

[string]$totalsize = num2size $totalbytes
$destdrive = resolve-drive (Convert-Path .)
$capacity = (Get-PSDrive ($destdrive -split ':')[0]).Free
if ($totalbytes -gt $capacity) {
    write-host -f red "* Not enough space on $destdrive"
    exit 1
}

for ($i=0; $i -lt $files.length; $i++) {
    Write-Progress `
        -Activity "Pasting to $(Convert-Path .)" `
        -Status ("Total Progress {0}/{1} files {2} total" `
            -f ($i + 1), $files.length, $totalsize) `
        -PercentComplete ($i / $files.length * 100)
    if ($cut) {
        Move-File $files[$i][0] $files[$i][1]
    } else {
        Copy-File $files[$i][0] $files[$i][1]
    }
}

if ($cut) {
    [Windows.Forms.Clipboard]::GetFileDropList() | %{
        if (test-path -PSPath $_ -type Container) {
            gi -force -PSPath $_ | Remove-Item -force -recurse
        }
    }
    [Windows.Forms.Clipboard]::Clear()
}

这篇关于可以复制和粘贴在Windows CMD中模拟?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆