Remove character from file in-place with native Windows tools - windows

I'd like to remove the last character off a large file. The restrictions are that:
the file has to be modified in-situ, without using the disk space required for a similar second file
it's a windows machine
I cannot copy any compiled code onto the machine so I cannot create a small c# program of c++ program to manipulate the file
this also means any non-native scripting is not available, like python.
As far as I know, this limits me to bat, VB (or JScript) but it does not look like there is a viable option in these. VB requires a TextStream to be created from a systemfile object, but then this stream I believe must be saved elsewhere, using diskspace.
Is there a way to do this simply?

Following the idea from Noodles (of course you need to have some .net framework version installed), you can try this
(save as trim.cmd and call as trim.cmd "fileToTrim.dat")
#if (#this==#isBatch) #then
#echo off
setlocal enableextensions disabledelayedexpansion
rem check arguments
set "fileToTrim=%~1"
if not exist "%fileToTrim%" goto :eof
rem search for a valid framework version
set "frameworks=%SystemRoot%\Microsoft.NET\Framework"
set "jsc="
for /f "tokens=* delims=" %%a in (
'dir /b /a:d /o:-n "%frameworks%\v*"'
) do if not defined jsc if exist "%frameworks%\%%a\jsc.exe" set "jsc=%frameworks%\%%a\jsc.exe"
if not defined jsc goto :eof
set "executable=%~dpn0.%random%.exe"
%jsc% /nologo /out:"%executable%" "%~f0"
if exist "%executable%" (
"%executable%" "%fileToTrim%"
del "%executable%" >nul 2>nul
)
endlocal
exit /b 0
#end
import System;
import System.IO;
var arguments:String[] = Environment.GetCommandLineArgs();
if (arguments.length > 1) {
var fi:FileInfo = new FileInfo(arguments[1]);
var fs:FileStream = fi.Open(FileMode.Open);
fs.SetLength (
Math.max(0, fi.Length - 1)
);
fs.Close();
};
This is far from efficient, the jscript code is compiled each time. Better directly write the program, compile and use. But just as an example ...

Related

Searching for partial path\filename in bat

Ok, so I've been bating (hehe) my head against a wall here.
I am looking for an option/code that would allow me to search for a partial path and/or filename from a .bat script that I would export to an outside file.
Now, "search", "export" and "outside file" is something I am fine with. The part that is giving me a headache is the "partial".
To elaborate.
I am looking for a folder called DATA and a file called userinfo.txt inside DATA.
Those are constant. So the path I have is DATA\userinfo.txt
I am also 99% certain that this folder will be in D:\ but thats not a concern right now. Where ever it is I'll find it.
But I cannot figure out how to look for a partial path\filename for the life of me.
Reason I have specified that DATA\userinfo.txt is a constant is due to other folders ability to be named arbitrarily. So in my below example 01-12-2016 does not have to be named according to that convention. For USA it would most likely be named 12-01-2016. It is also sometimes named 20161201 or 20160112 or on top of all that has a letter prefix such as d01-12-2016. On that note DATA is always DATA, which is why I said DATA is constant in my search. Another thing that will be the same is the grandparent folder. When i say "same" i mean "shared" between the two applications. It does not mean it will always be named "program" as in my example below.
Googling this and using things I know has got me nowhere.
Reason I cannot simply use
where /r d: userinfo.txt
is that that specific command will return hundreds of results as there is a userinfo.txt created for every.single.day the program was running and is stored separately.
Alternatively - if there would be a way to comb trough those hundreds of results and find the matching part that would also resolve my issue.
This however brings up another headache as there is usually more than one program with this exact file.
so in the example of
d:\users\path\program\storage\01-12-2016\userinfo.txt
d:\users\path\program\otherstorage\01-12-2016\userinfo.txt
d:\users\path\program\storage\02-12-2016\userinfo.txt
d:\users\path\program\otherstorage\02-12-2016\userinfo.txt
d:\users\path\program\storage\03-12-2016\userinfo.txt
d:\users\path\program\otherstorage\03-12-2016\userinfo.txt
d:\users\path\program\storage\04-12-2016\userinfo.txt
d:\users\path\program\otherstorage\04-12-2016\userinfo.txt
d:\users\path\program\storage\05-12-2016\userinfo.txt
d:\users\path\program\otherstorage\05-12-2016\userinfo.txt
d:\users\path\program\storage\06-12-2016\userinfo.txt
d:\users\path\program\otherstorage\06-12-2016\userinfo.txt
d:\users\path\program\storage\data\userinfo.txt
d:\users\path\program\otherstorage\data\userinfo.txt
Note: storage, otherstorage, storageother, storage2, storagegh are all arbitrary names as these folders are named accoring to end-user wishes.
I would want to export two separate variables for
d:\users\path\program\storage
and
d:\users\path\program\otherstorage
I would also need to do this for \data\userinfo.txt
So if searching for \data\userinfo.txt it would return
d:\users\path\program\storage\data\userinfo.txt
d:\users\path\program\otherstorage\data\userinfo.txt
I would also want to isolate both
d:\users\path\program\storage
and
d:\users\path\program\otherstorage
and use it as (separate) local variables.
I would need to note that installing/downloading any external scripting tools/aids would not be a suitable solution as I work on a lot of computers, most of which I do not have internet access and/or sufficient permissions for external downloads/installations so anything that is not integrated into the bat and needs to be imported separately is a bad idea.
Also, I am working on Windows XP SP3 but I would need this bat to be able to run on XP SP2, XP SP3, Windows 7, Windows 10, Windows NT, Windows 2000.
Any help would be appreciated.
Please note that
d:\users\path\program
would also be an acceptable variable. In this case I would manually amend the remainder of the path or would rely on end-user (my coworkers) input to complete the path correctly. The last has proven to be a fools errand.
The way that I've been handling it until now is to look for a .exe that I KNOW will be in both folders. This is a part of my code below edited to match the current example.
#echo off
SETLOCAL
echo Program will now look for program.exe and programgh.exe. Please input, when asked, matching part of the path for these files.
echo Example:
echo d:\users\path\program\storage\bin\program.exe
echo d:\users\path\program\otherstorage\bin\programgh.exe
echo In above example matching part is d:\users\path\program so you would enter that when prompted
echo Please do not input the last pathing mark: \ (backslash)
echo -------------searching---------------
::I am exporting errors to nul as I don't want them to be spammed by errors and other data that they would think is their fault
where /r c: program*.exe 2>nul
where /r d: program*.exe 2>nul
where /r e: program*.exe 2>nul
where /r f: program*.exe 2>nul
set /p dualpath="Please enter matching paths for program folder: "
After that I would proceed to work with %dualpath% variable.
As it usually happens (to me at least) most people would just copy the example path without taking a look at what the program has spat out and would be confused as to why the program did not work. Either that or would copy everything up to program.exe and programgh.exe - including the otherstorage\bin\ without noticing that \storage\ and \otherstorage\ do not match.
I think this now covers all the comments or additional questions and clarifies a bit better what I need. Thank you all for help so far and I hope that this is easier to understand.
If a Windows cmd command allows wildcards in a (partially or fully qualified) path then wildcards must be used only in the path leaf (i.e. the last item or container in the path). However, you could apply findstr regex to narrow command output e.g. as follows:
where /r d:\ userinfo.txt | findstr /I "\\storage2*\\data\\userinfo.txt"
above command wold narrow output to paths ending with \storage\data\userinfo.txt and \storage2\data\userinfo.txt
Another example - narrow output to paths ending with \storageX\data\userinfo.txt where X is either nothing or any decimal cipher [0-9]:
dir /B /S d:\userinfo.txt | findstr /I "\\storage[0-9]*\\data\\userinfo.txt"
Put the paths to environment variables (with _var prefix for easier next identification), e.g. _varstorage, _varstorage2, …
#ECHO OFF
SETLOCAL EnableExtensions
for /F "delims=" %%F in ('
dir /B /S "d:\userinfo.txt" ^| findstr /I "\\storage[0-9]*\\data\\userinfo.txt"') do (
for /D %%D in ("%%~dpF..") do (
set "_var%%~nxD=%%~fD"
rem %%~fD path
rem %%~nxD last item in above path
rem _var variable name prefix
)
)
rem show result:
set _var
See also next %%~nxD and %%~D explanation: Command Line arguments (Parameters): Parameter Extensions
If I got your intention right, the following script should do what you want:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_ROOT=D:\" & rem "D:\", "D:\users",..., or "D:\users\path\program"
set "_FILE=userinfo.txt"
rem // Initialise index:
set /A "INDEX=1"
rem // Search for the specified file in the given root directory:
for /F "delims=" %%F in ('dir /B /S "%_ROOT%\%_FILE%"') do (
rem // Iterate once over the grandparent directory itself:
for /D %%D in ("%%F\..\..") do (
rem // Resolve the path of the grantparent directory;
set "ITEM=%%~fD"
rem // Initialise flag (non-empty means not yet stored):
set "FLAG=#"
rem // Toggle delayed expansion to avoid trouble with exclamation marks:
setlocal EnableDelayedExpansion
rem // Iterate over all currently stored grantparent paths:
for /F "tokens=1,* delims==" %%V in ('2^> nul set $ARRAY[') do (
rem // Clear flag in case current grandparent has already been stored:
if /I "!%%V!"=="!ITEM!" set "FLAG="
)
rem // Check flag:
if defined FLAG (
rem // Flag is empty, so current grandparent needs to be stored:
set "$ARRAY[!INDEX!]=!ITEM!"
rem // Transfer stored grandparent over localisation barrier:
for /F "delims=" %%E in ("$ARRAY[!INDEX!]=!ITEM!") do (
endlocal
set "%%E"
)
rem // Increment index
set /A "INDEX+=1"
) else endlocal
)
)
rem // Retrieving final count of grandparent directories:
set /A "INDEX-=1"
rem // Return stored grandparent paths:
set $ARRAY[
endlocal
exit /B
This should return D:\users\path\programs\otherstorage and D:\users\path\programs\storage in your situation, which are stored in the variables $ARRAY[1] and $ARRAY[2], respectively. Due to the array-style variables, this approach is flexible enough to cover also cases where more than two grandparent directories are present.
Based on your above sample this batch
#Echo off
Set Search=\\data\\userinfo.txt
pushd "D:\Users\path\program
For /f "Delims=" %%A in (
'Dir /B/S/A-D userinfo.txt ^|findstr "%Search%$"'
) Do Call :Sub "%%~fA" "%%~dpA.."
Popd
Goto :Eof
:Sub FullName DrivePath
Echo Found %~nx1
Echo in %~dp1
Echo Granny %~nx2
Set "Granny=%~nx2"
Echo in %~dp2
Echo -------
Should give this output (only partially tested)
Found userinfo.txt
in D:\Users\path\program\storage\data\
Granny storage
in D:\Users\path\program\
-------
Found userinfo.txt
in D:\Users\path\program\storage2\data\
Granny storage2
in D:\Users\path\program\
-------
The backslash in Search has to be doubled as it is an escape char for findstr

How to use a volume label in a Windows path?

I want to copy files off a removable drive using a batch file, regardless of the drive letter it gets.
So far, no go. There don't seem to be any readily available commands or 3rd-party command-line tools that would handle paths based on volume labels.
I tried FreeFileSync, but it works in big batches, and I need precise file operations here. Also, it doesn't do deletions, and I need to MOVE files off the pendrive.
What piques my interest, however, is that issuing a nonsense command like...
C:\> cd MYPENDRIVE:
... results in quite an interesting bit in the default error message:
The filename, directory name, or volume label syntax is incorrect.
^^^^^^^^^^^^^^^^^^^
If this message is to be trusted, then it means there IS some correct syntax for putting a volume label in there. Or isn't there?
Note: I can settle for writing a small "getdriveletterforvolume" tool, if I have to, but I'd rather not reinvent the wheel. Also, during longer batch file operations the drive may be removed and replaced with another, at which point I'll need the operations to cease, and not continue on another drive that gets the same drive letter.
Note2: Using \\?\Volume{12345678.....} is a last resort, though it can be tamed to some extent, to build a rudimentary batch file like...
SET PENDRIVE=\\?\Volume{949a764e-a2f0-11e3-b710-6cf04975450b}
SET BACKUPDRIVE=\\?\Volume{e79091c4-5c2a-11e3-86f9-806e6f6e6963}
if exist %PENDRIVE% {
if exist %BACKUPDRIVE% {
move %PENDRIVE%\*.* %BACKUPDRIVE%
}
}
... but it's ugly and doesn't let me do any magic like giving two pendrives the same label to have them behave identically. I know it's not a common case, but hey, why limit one's options where there might be a ready solution?
Edit: Progress. I modified the subroutine to return a value as VOLUMEID:
CALL :GetVolumeID PENDRIVE
SET "PENDRIVE=%VOLUMEID%"
IF EXIST "%PENDRIVE%\" ECHO PENDRIVE is connected at %PENDRIVE%!
GOTO :eof
:GetVolumeID
FOR /F "skip=1" %%A in ('"wmic volume where label='%~1' get deviceid 2>/null"') do (
SET "VOLUMEID=%%A"
GOTO :eof
)
GOTO :eof
... but now if the pendrive is missing, wmic returns some empty-like value (NOT an empty string; it fails an if %%A=="" check) - and so IF EXIST \ ends up true. How do I eliminate an empty result like that..? I tried SET VOLUMEID=$FOO$ before the FOR, but it overwrites that with an empty value anyway.
Finally! Here's a proof of concept, for whomever finds it useful.
#ECHO OFF
CALL :GetVolumeID BACKUPDRIVE
SET "BACKUPDRIVE=%VOLUMEID%"
CALL :GetVolumeID PENDRIVE
SET "PENDRIVE=%VOLUMEID%"
if exist %PENDRIVE%\ (
if exist %BACKUPDRIVE%\ (
echo Emptying the pendrive.
move %PENDRIVE%\*.* %BACKUPDRIVE%\pendrive\
)
)
GOTO :eof
:GetVolumeID
SET VOLUMEID=$$$
FOR /F "tokens=1,* delims==" %%A IN ('"wmic volume where label='%~1' get deviceid /value 2>nul"') DO IF NOT "%%~B"=="" SET "VOLUMEID=%%~B"
SET "VOLUMEID=%VOLUMEID:~0,-2%"
GOTO :eof
I added the $ bogus value to be returned to fail an EXIST check.
The final SET VOLUMEID=%VOLUMEID... line removes the trailing backslash (for some reason it counts as TWO characters) so that paths written as %MYDRIVE%\file*.* look sane.
here's a subroutine that will push you to a drive by its name.It takes one argument - the drive label:
#echo off
:pushToLabel label
setlocal
for /f "skip=1 delims=:" %%A in ('"wmic logicaldisk where VolumeName='%~1' get name"') do (
set "drive=%%A:"
goto :break
)
:break
echo %drive%
endlocal && (
pushd %drive%
)
Here's a final proof of concept, for whomever finds it useful. Calling GetVolumeID sets a DRIVELETTER variable as return, in the "F:" form.
#ECHO OFF
CALL :GetVolumeID BACKUPDRIVE
SET "BACKUPDRIVE=%DRIVELETTER%"
CALL :GetVolumeID PENDRIVE
SET "PENDRIVE=%DRIVELETTER%"
if exist %PENDRIVE%\ (
if exist %BACKUPDRIVE%\ (
echo Emptying the pendrive.
move %PENDRIVE%\*.* %BACKUPDRIVE%\pendrive\
)
)
GOTO :eof
:GetVolumeID
SET DRIVELETTER=$$$
FOR /F "tokens=1,* delims==" %%A IN ('"wmic volume where label='%~1' get deviceid /value 2>nul"') DO IF NOT "%%~B"=="" SET "DRIVELETTER=%%~B"
SET "DRIVELETTER=%DRIVELETTER:~0,-2%"
GOTO :eof

Feed in a list of find and replace values with batch

I'm looking for a way to find and replace multiple words in a text file using a Windows batch script.
I know replacing a word can be done so with this bat script:
#echo off &setlocal
set "search=%1"
set "replace=%2"
set "textfile=Input.txt"
set "newfile=Output.txt"
(for /f "delims=" %%i in (%textfile%) do (
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:%search%=%replace%!"
echo(!line!
endlocal
))>"%newfile%"
del %textfile%
rename %newfile% %textfile%
Now, I just have to take it one step further and feed in the search and replace strings from another file similar to this format:
search_string1, replace_string1
search_string2, replace_string2
search_string3, replace_string3
.
.
.
I would think that I would somehow process the file line by line, and parse them into two variables (search, replace) and then feed that into the script above. Any thoughts? I'm new to Windows batch scripts and have never really made one before so mind my newbie questions.
This type of text replacements are slow and prone to fail when performed via a Batch file. I wrote FindRepl.bat program that is a Batch-JScript hybrid script that not only run much faster and with no errors, but it also allows to perform the multiple replacements you are looking for in just one processing pass of the data file. JScript is a programming language that is included in all Windows versions from XP on. Using FindRepl.bat program you may solve your problem this way:
#echo off
setlocal EnableDelayedExpansion
set "search="
set "replace="
for /F "tokens=1,2 delims=," %%a in (replacements.txt) do (
set "search=!search!|%%a"
set "replace=!replace!|%%b"
)
set "search=!search:~1!"
set "replace=!replace:~1!"
< Input.txt FindRepl =search /A =replace > Output.txt
Note that all text placed after the comma in the replacements file is the replacement string, including spaces.
You may download FindRepl.bat program from this site. Place it in the same folder of previous program or, better yet, in a folder included in %PATH%, so you may use it directly.

Recursively search for, and build, arbitrary VS solutions using a batch script w/ command line args

So, I want to be able to build an arbitrary number of VS solutions using a batch script. I would want the script to search for the given project names, and pass their filepaths to the VS CLI.The format would be along the lines of:
build_slns (debug|release) [proj1] [proj2] ... [projN]
The first arg would be the configuration, and all subsequent args would be project names. The part I'm having trouble with, is that these projects will all be in different subdirectories of my base code directory. So an example would be something like this:
build_slns debug foo bar foobar
And the .slns I want to build would be located like so:
Code\foo\foo.sln
Code\foo\bar\bar.sln
Code\foobar\foobar.sln
I believe I'll want to use FOR /F, but I'm just not familiar enough with batch to get it working the way I want it to. Any guidance here is greatly appreciated.
Something like this should work
#echo off
setlocal
::change the definition of cmd and root as needed
set cmd="C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe"
set root="d:\utils"
:loop
if "%~2" equ "" exit /b
echo Searching for %2
for /f "eol=: delims=" %%F in ('dir /b /s "%root%\%2.sln"') do (
echo Building %%F
%cmd% "%%F" /build %1
)
shift /2
goto :loop

Access clipboard in Windows batch file

Any idea how to access the Windows clipboard using a batch file?
To set the contents of the clipboard, as Chris Thornton, klaatu, and bunches of others have said, use %windir%\system32\clip.exe.
Update 2:
For a quick one-liner, you could do something like this:
powershell -sta "add-type -as System.Windows.Forms; [windows.forms.clipboard]::GetText()"
Capture and parse with a for /F loop if needed. This will not execute as quickly as the JScript solution below, but it does have the advantage of simplicity.
Updated solution:
Thanks Jonathan for pointing to the capabilities of the mysterious htmlfile COM object for retrieving the clipboard. It is possible to invoke a batch + JScript hybrid to retrieve the contents of the clipboard. In fact, it only takes one line of JScript, and a cscript line to trigger it, and is much faster than the PowerShell / .NET solution offered earlier.
#if (#CodeSection == #Batch) #then
#echo off
setlocal
set "getclip=cscript /nologo /e:JScript "%~f0""
rem // If you want to process the contents of the clipboard line-by-line, use
rem // something like this to preserve blank lines:
for /f "delims=" %%I in ('%getclip% ^| findstr /n "^"') do (
setlocal enabledelayedexpansion
set "line=%%I" & set "line=!line:*:=!"
echo(!line!
endlocal
)
rem // If all you need is to output the clipboard text to the console without
rem // any processing, then remove the "for /f" loop above and uncomment the
rem // following line:
:: %getclip%
goto :EOF
#end // begin JScript hybrid chimera
WSH.Echo(WSH.CreateObject('htmlfile').parentWindow.clipboardData.getData('text'));
Old solution:
It is possible to retrieve clipboard text from the Windows console without any 3rd-party applications by using .NET. If you have powershell installed, you can retrieve the clipboard contents by creating an imaginary textbox and pasting into it. (Source)
Add-Type -AssemblyName System.Windows.Forms
$tb = New-Object System.Windows.Forms.TextBox
$tb.Multiline = $true
$tb.Paste()
$tb.Text
If you don't have powershell, you can still compile a simple .NET application to dump the clipboard text to the console. Here's a C# example. (Inspiration)
using System;
using System.Threading;
using System.Windows.Forms;
class dummy {
[STAThread]
public static void Main() {
if (Clipboard.ContainsText()) Console.Write(Clipboard.GetText());
}
}
Here's a batch script that combines both methods. If powershell exists within %PATH%, use it. Otherwise, find the C# compiler / linker and build a temporary .NET application. As you can see in the batch script comments, you can capture the clipboard contents using a for /f loop or simply dump them to the console.
:: clipboard.bat
:: retrieves contents of clipboard
#echo off
setlocal enabledelayedexpansion
:: Does powershell.exe exist within %PATH%?
for %%I in (powershell.exe) do if "%%~$PATH:I" neq "" (
set getclip=powershell "Add-Type -AssemblyName System.Windows.Forms;$tb=New-Object System.Windows.Forms.TextBox;$tb.Multiline=$true;$tb.Paste();$tb.Text"
) else (
rem :: If not, compose and link C# application to retrieve clipboard text
set getclip=%temp%\getclip.exe
>"%temp%\c.cs" echo using System;using System.Threading;using System.Windows.Forms;class dummy{[STAThread]
>>"%temp%\c.cs" echo public static void Main^(^){if^(Clipboard.ContainsText^(^)^) Console.Write^(Clipboard.GetText^(^)^);}}
for /f "delims=" %%I in ('dir /b /s "%windir%\microsoft.net\*csc.exe"') do (
if not exist "!getclip!" "%%I" /nologo /out:"!getclip!" "%temp%\c.cs" 2>NUL
)
del "%temp%\c.cs"
if not exist "!getclip!" (
echo Error: Please install .NET 2.0 or newer, or install PowerShell.
goto :EOF
)
)
:: If you want to process the contents of the clipboard line-by-line, use
:: something like this to preserve blank lines:
for /f "delims=" %%I in ('%getclip% ^| findstr /n "^"') do (
set "line=%%I" & set "line=!line:*:=!"
echo(!line!
)
:: If all you need is to output the clipboard text to the console without
:: any processing, then remove the above "for /f" loop and uncomment the
:: following line:
:: %getclip%
:: Clean up the mess
del "%temp%\getclip.exe" 2>NUL
goto :EOF
Slimming it down (on a new enough version of Windows):
set _getclip=powershell "Add-Type -Assembly PresentationCore;[Windows.Clipboard]::GetText()"
for /f "eol=; tokens=*" %I in ('%_getclip%') do set CLIPBOARD_TEXT=%I
First line declares a powershell commandlet.
Second line runs and captures the console output of this commandlet into the CLIPBOARD_TEXT enviroment variable (cmd.exe's closest way to do bash style backtick ` capture)
Update 2017-12-04:
Thanks to #Saintali for pointing out that PowerShell 5.0 adds Get-Clipboard as a top level cmdlets, so this now works as a one liner:
for /f "eol=; tokens=*" %I in ('powershell Get-Clipboard') do set CLIPBOARD_TEXT=%I
The clip command is good to pipe text to the clipboard, but it can't read from the clipboard. There is a way in vbscript / javascript to read / write the clipboard but it uses automation and an invisible instance if Internet Explorer to do it so its pretty fat.
The best tool I've found for working the clipboard from script is Nirsoft's free NirCmd tool.
http://www.nirsoft.net/utils/nircmd.html
Its like a swiss army knife of batch commands all in one small .exe file. For clipboard commands you would say someting like
nircmd clipboard [Action] [Parameter]
Plus you can directly refer to clipboard contents in any of its commands using its ~$clipboard$ variable as an argument. Nircmd also has commands in it to run other programs or commands from so it is possible to use it to pass the clipboard contents as an argument to other batch commands this way.
Clipboard actions:
set - set the specified text into the clipboard.
readfile - set the content of the specified text file into the clipboard.
clear - clear the clipboard.
writefile - write the content of the clipboard to a file. (text only)
addfile - add the content of the clipboard to a file. (text only)
saveimage - Save the current image in the clipboard into a file.
copyimage - Copy the content of the specified image file to the clipboard.
saveclp - Save the current clipboard data into Windows .clp file.
loadclp - Load Windows .clp file into the clipboard.
Note that most programs will always write a plain text copy to the clipboard even when they are writing a special RTF or HTML copy to the clipboard but those are written as content using a different clipboard format type so you may not be able to access those formats unless your program explicitly requests that type of data from the clipboard.
Best way I know, is by using a standalone tool called WINCLIP .
You can get it from here: Outwit
Usage:
Save clipboard to file: winclip -p file.txt
Copy stdout to clipboard: winclip -c Ex: Sed 's/find/replace/' file | winclip -c
Pipe clipboard to sed: winclip -p | Sed 's/find/replace/'
Use winclip output (clipboard) as an argument of another command:
FOR /F "tokens=* usebackq" %%G in ('winclip -p') Do (YOUR_Command %%G ) Note that if you have multiple lines in your clipboard, this command will parse them one by one.
You might also want to take a look at getclip & putclip tools: CygUtils for Windows but winclip is better in my opinion.
With Vista or higher, it's built in. Just pipe output to the "clip" program.
Here's a writeup (by me):
http://www.clipboardextender.com/general-clipboard-use/command-window-output-to-clipboard-in-vista
The article also contains a link to a free utility (written by Me, I think) called Dos2Clip, which can be used on XP.
EDIT: I see that I've gotten the question backwards, my solution OUTPUTS to the clipboard, doesn't read it. sorry!
Update: Along with Dos2Clip, is Clip2Dos (in the same zip), which will send the clipboard text to stdout. So this should work for you. Pascal source is included in the zip.
To retrive clipboard content from your batch script: there is no "pure" batch solution.
If you want an embed 100% batch solution, you will need to generate the other language file from your batch.
Here is a short and batch embed solution which generate a VB file (Usually installed on most windows)
Since all answers are confusing, here my code without delays or extra windows to open stream link copied from clipboard:
#ECHO OFF
//Name of TEMP TXT Files
SET TXTNAME=CLIP.TXT
//VBA SCRIPT
:: VBS SCRIPT
ECHO.Set Shell = CreateObject("WScript.Shell")>_TEMP.VBS
ECHO.Set HTML = CreateObject("htmlfile")>>_TEMP.VBS
ECHO.TXTPATH = "%TXTNAME%">>_TEMP.VBS
ECHO.Set FileSystem = CreateObject("Scripting.FileSystemObject")>>_TEMP.VBS
ECHO.Set File = FileSystem.OpenTextFile(TXTPATH, 2, true)>>_TEMP.VBS
ECHO.File.WriteLine HTML.ParentWindow.ClipboardData.GetData("text")>>_TEMP.VBS
ECHO.File.Close>>_TEMP.VBS
cscript//nologo _TEMP.VBS
:: VBS CLEAN UP
DEL _TEMP.VBS
SET /p streamURL=<%TXTNAME%
DEL %TXTNAME%
:: 1) The location of Player
SET mvpEXE="D:\Tools\Programs\MVP\mpv.com"
:: Open stream to video player
%mvpEXE% %streamURL%
#ECHO ON
Piping output to the clipboard is provided by clip, as others have said. To read input from the clipboard, use the pclip tool in this bundle. And there's tons of other good stuff in there.
So for example, you're going through an online tutorial and you want to create a file with the contents of the clipboard...
c:\>pclip > MyNewFile.txt
or you want to execute a copied command...
c:\>pclip | cmd
This might not be the exact answer, but it will be helpful for your Quest.
Original post:
Visit https://groups.google.com/d/msg/alt.msdos.batch/0n8icUar5AM/60uEZFn9IfAJ
Asked by Roger Hunt
Answered by William Allen
Much Cleaner Steps:
Step 1) create a 'bat' file named Copy.bat in desktop using any text editors and copy and past below code and save it.
#ECHO OFF
SET FN=%1
IF ()==(%1) SET FN=H:\CLIP.TXT
:: Open a blank new file
REM New file>%FN%
ECHO.set sh=WScript.CreateObject("WScript.Shell")>_TEMP.VBS
ECHO.sh.Run("Notepad.exe %FN%")>>_TEMP.VBS
ECHO.WScript.Sleep(200)>>_TEMP.VBS
ECHO.sh.SendKeys("^+{end}^{v}%%{F4}{enter}{enter}")>>_TEMP.VBS
cscript//nologo _TEMP.VBS
ECHO. The clipboard contents are:
TYPE %FN%
:: Clean up
DEL _TEMP.VBS
SET FN=
Step 2) create a Blank text file (in my case 'CLIP.txt' in H Drive) or anywhere, make sure you update the path in Copy.bat file under 'FN=H:\CLIP.txt' with your destination file path.
That's it.
So, basically when you copy any text from anywhere and run Copy.bat file from desktop, it updates CLIP.txt file with the Clipboard contents in it and saves it.
Uses:
I use it to transfer data from remotely connected machines where copy/paste is disabled between different connections; where shared drive (H:) is common to all Connections.
Multiple lines
The problem is resolved, but disappointment remains.
I was forced to split one command into two.
First of them well understands the text and service characters, but does not understand the backspace.
The second understands backspace, but does not understand many service characters.
Can anyone unite them?
Notepad ++, in the place where it should open, is commented out because sometimes the window does not get access to enter characters and therefore you need to make sure that it is active.
Of course, it is better to enter characters using the PID of the notebook process, but ...
The request from wmic opens for a long time, so do not close the notepad window until the bat file is closed.
#echo off
set "like=Microsoft Visual C++"
set "flag=0"
start /max C:\"Program Files\Notepad++\notepad++.exe" -nosession -multiInst
( set LF=^
%= NEWLINE =%
)
set ^"NL=^^^%LF%%LF%^%LF%%LF%^^"
::------------------
setlocal enabledelayedexpansion
for /f "usebackq delims=" %%i in ( `wmic /node:"papa" product where "Name like '%%%like%%%'" get * ^| findstr /r /v "^$"`) do (
for /f tokens^=1^ delims^=^" %%a in ("%%i") do set str=%%a
if "!flag!"=="0" (
::start /max C:\"Program Files\Notepad++\notepad++.exe" -nosession -multiInst& set "flag=1"
for /f "delims=" %%i in ('mshta "javascript:new ActiveXObject('WScript.Shell').SendKeys('{BS}{BS}{BS}{BS}');close(new ActiveXObject('Scripting.FileSystemObject'));"') do set
set flag=1
)
#set /P "_=%%str%%"<NUL|clip
for /f "delims=" %%i in ('mshta "javascript:new ActiveXObject('WScript.Shell').SendKeys('^v');close(new ActiveXObject('Scripting.FileSystemObject'));"') do set
(echo %%NL%%)|clip
for /f "delims=" %%i in ('mshta "javascript:new ActiveXObject('WScript.Shell').SendKeys('^v');close(new ActiveXObject('Scripting.FileSystemObject'));"') do set
)
setlocal disabledelayedexpansion
Here's one way with mshta:
#echo off
:printClip
for /f "usebackq tokens=* delims=" %%i in (
`mshta "javascript:Code(close(new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write(clipboardData.getData('Text'))));"`
) do (
echo cntent of the clipboard:
echo %%i
)
the same thing for accessing it directly from console:
for /f "usebackq tokens=* delims=" %i in (`mshta "javascript:Code(close(new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write(clipboardData.getData('Text'))));"`) do #echo %i

Resources