0

I'd like to create a batch file that will copy all of the .out files in a folder to the clipboard. (Similar to highlighting multiple files, right-clicking, and selecting copy). I can't seem to find a way to copy files without knowing the destination. Is it possible?

Thanks.

Paul
  • 303
  • 1
  • 5
  • 20

3 Answers3

4

When you right-click a file within Windows Explorer and choose Copy, you aren't copying that file's path as text data. Try it. Right-click-copy a file on your Desktop and try to paste in Notepad or some other text editor. Nothing, right?

No, you need to use some .NET methods to copy the file pointers in a way that Windows will let you Paste to perform a file copy action. This is done by invoking the Clipboard.SetFileDropList() method.

Here's a batch + PowerShell script solution that exposes this method. Save it with a .bat extension.

<# : batch portion
@echo off & setlocal

set "filemask=*.out"
powershell -STA -noprofile "iex (${%~f0} | out-string)"
goto :EOF

: end batch / begin PowerShell hybrid code #>

$collection = new-object Collections.Specialized.StringCollection
gci $env:filemask | %{ $collection[$collection.Add($_.FullName)] }

Add-Type -AssemblyName System.Windows.Forms
[Windows.Forms.Clipboard]::SetFileDropList($collection)

Following Paul's request, a couple of minor tweaks will allow you to select files via regexp, so you can match multiple extensions.

<# : batch portion
@echo off & setlocal

set "rxp=\.(out|dat|log)$"
powershell -STA -noprofile "iex (${%~f0} | out-string)"
goto :EOF

: end batch / begin PowerShell hybrid code #>

$collection = new-object Collections.Specialized.StringCollection
gci | ?{ $_.Name -match $env:rxp } | %{ $collection[$collection.Add($_.FullName)] }

Add-Type -AssemblyName System.Windows.Forms
[Windows.Forms.Clipboard]::SetFileDropList($collection)

And just because I felt like accepting LinuxDisciple's challenge, here's a solution that accepts file masks from the command line.

<# : batch portion
@echo off & setlocal

if "%~1"=="" (
    echo Usage: %~nx0 filemask [filemask [filemask [...]]]
    echo    example: %~nx0 *.jpg *.gif *.bmp
    goto :EOF
)

(for %%I in ("%~f0";%*) do @for %%# in ("%%~I") do @echo(%%~f#) | ^
powershell -STA -noprofile "$argv = $input | ?{$_}; iex (${%~f0} | out-string)"

goto :EOF
: end batch / begin powershell #>

$col = new-object Collections.Specialized.StringCollection
$argv[1..($argv.length-1)] | ?{$_.length -gt 3 -and (test-path $_)} | %{$col[$col.Add($_)]}

if ($col.Count) {
    Add-Type -AssemblyName System.Windows.Forms
    [Windows.Forms.Clipboard]::SetFileDropList($col)
}
Community
  • 1
  • 1
rojo
  • 24,000
  • 5
  • 55
  • 101
  • Concise AND actually works! Nice! Going to make a version that takes command-line input now. – LinuxDisciple Mar 30 '16 at 03:11
  • 1
    Cool thing is that you can actually use the second solution to select files from multiple directories for a single copypaste action. `batfile.bat *.txt *.docx "folder name\*.pdf"` for example. – rojo Mar 30 '16 at 15:47
  • Thanks for the great examples. Sorry to ask one more question, but if I wanted to modify the first example to search for multiple file extensions (.out, .dat, etc), is there a simple way to modify the code? I'm already passing a different argument, so wasn't sure if the second example will work. – Paul Mar 30 '16 at 19:29
  • 1
    @Paul Yep. You might find it useful to search by regex, rather than by wildcard globs. I inserted an example after the first solution. – rojo Mar 30 '16 at 20:17
2

See Access clipboard in Windows batch file
It uses .getData to get info from the clipboard, but there's also a .setData option that will allow you to populate the copy/paste buffer with file data. The answer to your question is that there's no way to do it directly with batch, but using this WSH hack, you can at least avoid using tools that are external to Windows.

Community
  • 1
  • 1
LinuxDisciple
  • 2,289
  • 16
  • 19
1
type *.out|clip

will concatenate the *.out files and place the result on the clipboard.

Magoo
  • 77,302
  • 8
  • 62
  • 84
  • Nice... never heard of... and now wondering about cutting files to clipboard, i.e., move. Is it possible? – statosdotcom Mar 29 '16 at 20:55
  • Thanks, but that appears to copy the contents of the file to the clipboard. I would like to copy the file (or pointer to the file, or whatever Windows does). Is that possible? – Paul Mar 29 '16 at 20:59
  • The solution above will copy the content of the files, not what you'd get by going into Explorer, highlighting a selection of files, and choosing 'copy'. – LinuxDisciple Mar 29 '16 at 21:02
  • So - you want to copy the file**NAMES** - is that correct? – Magoo Mar 29 '16 at 22:54
  • I'm looking to copy a pointer (or whatever Windows does when you copy a file) to the files. – Paul Mar 30 '16 at 14:30