On windows server 2012, I can see the number of files with the following command but I need to print this file number in []. I have not reached a conclusion in my research on how it is done, can you help?
dir / b / s / a-d | find / v / c "::"
The output of this command is: 213123,
I [33432] (must be in square brackets) I want to write this.
Windows version: Windows Server 2012
How can I resolve it?
Use a FOR /F statement in a .bat script to generate the count and print it out.
FOR /F %%a IN ('DIR /B /S /A:-D ^| FIND /V /C "::"') DO (ECHO [%%a])
If this is done at the command line (not in a .bat script), then do not double the percent character.
FOR /F %a IN ('DIR /B /S /A:-D ^| FIND /V /C "::"') DO (ECHO [%a])
If you wanted to push ahead into PowerShell, you could use:
Get-ChildItem -File | Measure-Object | ForEach-Object { '[' + $_.Count + ']' }
Or, with all the cryptic aliases that should never be written into a script:
gci -File|measure|%{'['+$_.Count+']'}
Related
I have been trying to make this work for longer than I care to admit but for some reason I cannot figure it out. I usually work with Linux/Unix.
I simply want to search a directory for all instances where a filename matches a string.
Some things I have tried:
dir /s "/path/to/Test*"
dir /s/b "C:/path/to/Test*"
Additionally, I am hoping to return something that can easily be imported into an array. Something without unnecessary information. All I need Is the path or at the very least the filename for each file matched.
Edit: I dont want information like this (if possible)
Volume in drive C is OS
Volume Serial Number is...
Edit: Test* is intended to indicate all filenames beginning with Test. So TestA, TestB, & TestC should all match.
The same commands work on Linux, Mac, and Windows. http://github.com/PowerShell/PowerShell/
PS C:\src> (Get-ChildItem -Recurse -File -Path 'C:/src/d2' -Filter 'test*').FullName
C:\src\d2\test.bat
C:\src\d2\test.ps1
C:\src\d2\test.sql
C:\src\d2\test.txt
C:\src\d2\copyt\test.txt
Using command aliases, it can be shorter for interactive use. But, aliases are not a good practice for scripts.
PS C:\src> (ls -r -file 'C:/src/d2/test*').FullName
C:\src\d2\test.bat
C:\src\d2\test.ps1
C:\src\d2\test.sql
C:\src\d2\test.txt
C:\src\d2\copyt\test.txt
If you want an array, this will make one.
PS C:\src> $files = (ls -r -file 'C:/src/d2/test*').FullName
PS C:\src> $files.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
Replace directory separators with -replace.
(Get-ChildItem -Recurse -Path 'C:/src/d2' -Filter 'test.*').FullName -replace '\\','/'
Join them to a single line with -join. This join uses a COMMA. Note that if the join uses a COLON in *NIX-style, it will not work well on Windows.
PS C:\src> (Get-ChildItem -Recurse -Path 'C:/src/d2' -Filter 'test.*').FullName -replace '\\','/' -join (',')
C:/src/d2/test.bat,C:/src/d2/test.ps1,C:/src/d2/test.sql,C:/src/d2/test.txt,C:/src/d2/copyt/test.txt
If you need a PATH-style separator, use:
(Get-ChildItem -Recurse -Path 'C:/src/d2' -Filter 'test.*').FullName -replace '\\','/' -join ([IO.Path]::PathSeparator)
I've just been searching for all files, called "test.*" all over my C:-drive, using this simple command:
dir /S C:\test*
Although I just mention the directory C:\, the /S makes sure all subfolders are used too. In top of that, there are no double quotes, as you can see.
Does this solve your issue?
Sorry, I didn't see that you're used working with UNIX/Linux, so here I have an approach you'll prefer:
forfiles /P C:\ /S /M test* /C "cmd /c echo #path"
This does the following:
/P C:\ Start looking in C:\
/S Search through subdirectories
/M test* Filename looks like "test*"
/C <cmd> When found, launch <cmd>
"cmd /c echo #path" Echo (write to output) the complete path of the found file or directory
This will give you a list of files and directories, written as full paths, something like:
"C:\Octave\Octave-5.2.0\mingw64\bin\test-libiberty.exe"
"C:\Octave\Octave-5.2.0\mingw64\bin\test-lua.exe"
"C:\Octave\Octave-5.2.0\mingw64\bin\test-tinyxml.exe"
"C:\Octave\Octave-5.2.0\mingw64\include\llvm\Testing" <-- this is a directory
"C:\Octave\Octave-5.2.0\mingw64\include\wx-3.0\wx\testing.h"
...
Which resembles a lot the typical UNIX/Linux results, you're used to.
More information about forfiles can be found, launching forfiles /?.
Based upon your statement, "I am hoping to return something that can easily be imported into an array", I'd assume you're probably looking for something more like this:
#Echo Off
Rem Ensure that extensions are enabled (required for SET and FOR commands)
SetLocal EnableExtensions
Rem Ensures that there are no existing variables in the environment with names beginning with file[
For /F "Delims==" %%G In ('" Set file[ 2> NUL "') Do Set "%%G="
Rem Gets every file matching the glob test* in the tree rooted at "C:\path\to"
Rem and defines an incremented variable name for each, beginning at %file[1]%
For /F "Tokens=1,* Delims=]" %%G In (
'" Dir /B /S /A-D "C:\path\to\test*" 2> NUL | "%__AppDir__%find.exe" /N /V "" "'
) Do Set "file%%G]=%%H"
Rem An example line to show you all of the variables you have now defined
Set file[ 2> NUL
Rem Pause the script to ensure that you have been able to read any output
Pause
Rem An example line to show you all the first defined variable value
Echo=%file[1]%
Rem Pause the script to ensure that you have been able to read any output
Pause
...and here it is without the Remarks:
#Echo Off
SetLocal EnableExtensions
For /F "Delims==" %%G In ('" Set file[ 2> NUL "') Do Set "%%G="
For /F "Tokens=1,* Delims=]" %%G In (
'" Dir /B /S /A-D "C:\path\to\test*" 2> NUL | "%__AppDir__%find.exe" /N /V "" "'
) Do Set "file%%G]=%%H"
Set file[ 2> NUL
Pause
Echo=%file[1]%
Pause
Don't forget to change C:\path\to\test* as required for your specific location and glob.
I'm trying to create a list of files created yesterday.
I've got the below working without /c:"cmd /c echo #path" but I want the full path.
forfiles /s /d -1 /m *.txt /c:"cmd /c echo #path" > a.txt
forfiles /s /m *.txt /c:"cmd /c echo #path" > b.txt
FOR /f "delims=; tokens=*" %%X IN ('findstr /v /g:a.txt b.txt') DO (
echo %%X
)
What is the best way to get around the issue with using findstr with a path containing backslashes? Do I need to replace all the backslashes in the comparison files with some other symbol and then change it back later or is there an easier way to do it in the findstr line?
The findstr command checks the very first search expression and changes to regular expression mode when a meta-character is found or to literal mode otherwise, unless you explicitly predefine the mode by /L (literal) or /R (regular expression).
But findstr is a nasty beast since there are still some problems even with /L:
wrong results may be returned with multiple literal search strings, unless you specify /I to do case-insensitive searches; but this is not a problem here anyway since you are dealing with directory and file names, which are treated case-insensitively by Windows anyway;
although in literal mode, escaping of meta-characters like ., [, ], ^, $, \, * and ? still occurs when there is a \ in front; you could just double all \ to work around that;
So the following code should work in most situations; delayed expansion is enabled herein by cmd /V, which is required to read the interim variable FILE that is written and read in the same command line:
forfiles /S /M "*.txt" /D -1 /C "cmd /C if #isdir==FALSE (set FILE=#path) & cmd /V /C echo(!FILE:\=\\!" > "exclude.txt"
forfiles /S /M "*.txt" /C "cmd /C if #isdir==FALSE echo #path" > "all.txt"
for /F "delims=" %%X in ('findstr /V /L /I /X /G:"exclude.txt" "all.txt"') do (
echo(%%X
)
I inserted if #isdir==FALSE here to not match directories whose names end in .txt. Also I added /X to findstr in order to match whole lines/paths only.
Regard that literal findstr search strings are limited to a length of 511 bytes (after doubling \), which can easily be reached with file paths.
However, what about a different approach that avoids findstr at all?
Here is a post I once provided for returning items newer than a relative date with forfiles: FORFILES date -after- (date calc in cmd file).
I prefer powershell for such tasks:
Get-ChildItem -Path "C:\Users\tivrick" -Recurse -ErrorAction SilentlyContinue | Where-Object { -Not $_.PSIsContainer -And $_.CreationTime.Date -Eq (Get-Date).Date.AddDays(-1) } | Select-Object -ExpandProperty FullName
If you really need to run that from a batch-file:
#PowerShell -NoP "GCI "C:\Users\tivrick" -R -EA SilentlyContinue|?{!$_.PSIsContainer -And $_.CreationTime.Date -Eq (Get-Date).Date.AddDays(-1)}|Select -Exp FullName"
for example i need to search for the file
hidebarVersion0.2.exe
I only know hidebarVersion but 0.2 will change each time ?
So I need to take that name each time and use it in another command like this
hidebarVersion0.2.exe -t -very -near
? how to script this in Windows ?
You can use get-childitem in the Directory to get the exact Name and then start an process with start:
$a = get-childitem hidebar* | sort name -desc | select -first 1
start $a.fullname
It will run that hidebar*.exe with the highest =newest filename.
You can use something like this:
#echo off
for /f "delims=" %%G in ('dir /a /b /s hidebarVersion*.exe') do "%%G" -t -very -near
To use it on the command prompt instead of inside a batch file use this:
for /f "delims=" %G in ('dir /a /b /s hidebarVersion*.exe') do "%G" -t -very -near
The command dir /a /b /s hidebarVersion*.exe finds a file matching hidebarVersion*.exe in the current directory or any of the subdirectories, and returns it in bare (/b) format.
Is there a way to extract/copy the fist X number of lines from a file and input them into another file with a single command using the windows command prompt?
I can delete the first X number of lines using:
more +X [file_containing data] > [file_to_export_data_to]
If the head command would work I think I could just do this:
head -X [file_containing data] > [file_to_export_data_to]
But that unfortunately does not work.
It would be great if Windows had a "less" command but again no luck.
I'm a complete novice when it comes to this stuff so I'm sure I'm missing something obvious. I don't want to install anything or use something other than the command prompt.
Thanks
the simplest one-command solution is to use Powershell Get-Content.
N - number of lines.
From the begining of file:
Get-Content -Head N file.txt
From the end of file:
Get-Content -Tail N file.txt
You can use PowerShell from the cmd.exe console:
powershell -command "& {get-content input.txt|select-object -first 10}" >output.txt
You could create a DOSKEY macro to make it easier to use from the command line:
doskey head=powershell -command "& {get-content $1|select-object -first $2}"
Usage:
head input.txt 10 >output.txt
But you cannot use a DOSKEY macro within a batch script.
You could create a head.bat script instead and place it in a folder that is included in your PATH:
head.bat
#powershell -command "& {get-content %1|select-object -first %2}"
From the command line, you would use head input.txt 10 >output.txt
From within a batch script, you would use call head input.txt 10 >output.txt
I chose not to have the output file as a parameter in case you want to simply display the result to the screen instead of writing to a file.
In order to get correct utf8 output, do the following in powershell
chcp 65001
$OutputEncoding = New-Object -typename System.Text.UTF8Encoding
get-content input.txt -encoding UTF8 |select-object -first 10000 > output.txt
This will get first 10000 lines of input.txt (file in utf8 format) to output.txt with correct encoding.
(#FOR /f "tokens=1* delims=:" %a IN ('findstr /n "^" "standardwaffle.txt"') DO #IF %a leq 7 ECHO(%b)>u:\junk.txt
would extract the first 7 lines of standardwaffle.txt to u:\junk.txt so here it is in one cmd line - but I'd defy you to enter that reliably.
It would also remove any leading : on a source line.
#ECHO OFF
SETLOCAL
IF %1 lss 0 (SET /a line=-%1) ELSE (SET /a line=%1)
FOR /f "tokens=1* delims=:" %%a IN ('findstr /n "^" "%~2"') DO IF %%a leq %line% ECHO(%%b
GOTO :EOF
This batch, saved as head.bat placed anywhere on your path would allow you to use
head -n standardwaffle.txt >junk.txt
to extract the first n lines of standardwaffle.txt to junk.txt
the - would be optional
but this involves installing the batch on your machine. Is that banned by your "no installing" requirement, or is "installing" meant only for 3rd party utilities?
Set Inp = WScript.Stdin
Set Outp = Wscript.Stdout
x = 0
Do Until Inp.AtEndOfStream
x = x + 1
OutP.WriteLine Inp.Readline
If x = 5 then Exit Do
Loop
This prints lines 1 to 5. To use
cscript //nologo <path to script.vbs> <inputfile >outputfile
you can use this:
break>"%temp%\empty"&&fc "%temp%\empty" "%file_to_process%" /lb X /t |more +4 | findstr /B /E /V "*****"
where you should replace the X with the lines you want.Or name this head.bat :
break>"%temp%\empty"&&fc "%temp%\empty" "%file_to_process%" /lb %~1 /t |more +4 | findstr /B /E /V "*****"
If you wanted to stick to simple Windows commands you could use this but would be a little slow for large files ;-) (I've added a second solution below that works better :-) this extracts the last 100 records of any length of file)
find /n " " <test.txt >test.tmp
for /l %%i in (1,1,100) do find "[%%i]" <test.tmp >test.tmp2
for /f "delims=] tokens=2" %%i in (test.tmp2) do echo %%i >>test.new
del test.tmp
del test.tmp2
move /y test.new test.txt
find /v /n "" <test.txt >test.tmp
for /f "delims=: tokens=2 %%i in ('find /v /c "" test.txt') do set /a NR=%%i
set /a NS=%NR%-100
for /l %%i in (%NS%, 1, %NR%) do find "[%%i]" <test.tmp >>test.tmp2
for /f %%i "delims=] tokens=2 %%i in (test.tmp2) do echo %%i >>test.new
move /y test.new test.txt
No need to read whole file; just extract the required lines (head) from beginning of file:
set file=<file>
set line=<required first few lines>
type nul > tmp & fc tmp "%file%" /lb %line% /t | find /v "*****" | more +2
A single line example to extract first 9 lines from file.txt & write into nine.txt
for /f "tokens=* delims=[" %i in ('type "file.txt" ^| find /v /n "" ^| findstr /b /r \[[1-9]\]') do set a=%i& set a=!a:*]=]!& echo:!a:~1!>> nine.txt
Preserves blank lines, lines starting with semicolon, leading spaces and preserves delimiter and whitespaces.
Tested on Win 10 x64 CMD
I just want to know how can I get all the names of the folders in a current directory. For example in my current directory I have three folders:
stackoverflow
reddit
codinghorror
Then when I execute my batch script all the three folders will print in the screen.
How can I achieve this?
Using batch files:
for /d %%d in (*.*) do echo %%d
If you want to test that on the command line, use only one % sign in both cases.
On Windows, you can use:
dir /ad /b
/ad will get you the directories only
/b will present it in 'bare' format
EDIT (reply to comment):
If you want to iterate over these directories and do something with them, use a for command:
for /F "delims=" %%a in ('dir /ad /b') do (
echo %%a
)
note the double % - this is for use in a batch, if you use for on the command line, use a single %.
added the resetting of default space delims in response to #Helen's comment
With PowerShell:
gci | ? { $_.PSIsContainer }
Old Answer:
With PowerShell:
gci | ? {$_.Length -eq $null } | % { $_.Name }
You can use the result as an array in a script, and then foreach trough it, or whatever you want to do...
For getting all the subfolders of a specific directory and display it in CMD :
#echo off
dir C:\input /s /b /o:n /a:d
Pause&Exit
For getting all the subfolders of a specific directory and save it in a text file :
dir C:\your_directory /s /b /o:n /a:d > output.txt