equivalent of (dir/b > files.txt) in PowerShell - powershell

dir/b > files.txt
I guess it has to be done in PowerShell to preserve unicode signs.

Get-ChildItem | Select-Object -ExpandProperty Name > files.txt
or shorter:
ls | % Name > files.txt
However, you can easily do the same in cmd:
cmd /u /c "dir /b > files.txt"
The /u switch tells cmd to write things redirected into files as Unicode.

Get-ChildItem actually already has a flag for the equivalent of dir /b:
Get-ChildItem -name (or dir -name)

Simply put:
dir -Name > files.txt

In PSH dir (which aliases Get-ChildItem) gives you objects (as noted in another answer), so you need to select what properties you want. Either with Select-Object (alias select) to create custom objects with a subset of the original object's properties (or additional properties can be added).
However in this can doing it at the format stage is probably simplest
dir | ft Name -HideTableHeaders | Out-File files.txt
(ft is format-table.)
If you want a different character encoding in files.txt (out-file will use UTF-16 by default) use the -encoding flag, you can also append:
dir | ft Name -HideTableHeaders | Out-File -append -encoding UTF8 files.txt

Since powershell deals with objects, you need to specify how you want to process each object in the pipe.
This command will get print only the name of each object:
dir | ForEach-Object { $_.name }

Just found this great post, but needed it for sub directories as well:
DIR /B /S >somefile.txt
use:
Get-ChildItem -Recurse | Select-Object -ExpandProperty Fullname | Out-File Somefile.txt
or the short version:
ls | % fullname > somefile.txt

I am using:
(dir -r).FullName > somefile.txt
and with filter for *.log:
(dir -r *.log).FullName > somefile.txt
Note:
dir is equal to `gci` but fits the naming used in cmd
-r recursive (all subfolders too)
.FullName is the path only

Related

Create text file containing a list of all files of a certain type with their filesize

I want to create a text file with all filenames of a certain filetype plus the filesize, recursively from a specified directory and all subdirectories.
For example: Listing all .jpg files plus their sizes from a huge photo-collection.
I have found several similar questions, but not this specific listing.
One did this with the full path name, but I don't need this and it would become very long.
Another lists all files, but without size.
Another lists all filenames with size, but I can't specify a filetype.
This PowerShell command creates the desired list, but I don't know how to limit it to a certain filetype (e.g. .jpg)
gci -rec|?{!$_.PSIsContainer}|%{"$($_.Fullname) $($_.Length)"} >filelist.txt
This batch file lists all .jpg's, but without showing the filesize.
dir /b /s z:\Filme\*.jpg > list1.txt
for /f "tokens=*" %%A in (list1.txt) do echo %%~nxA >> list.txt
del list1.txt
Could anyone edit one of these? so I get the desired list, or come up with a different solution?
Could anyone edit one of these so I get the desired list?
You are almost there with the batch script.
%~z1 will display the file size (in bytes).
You can also get rid of the temporary file by using a slightly different version of the for command.
Use the following batch file:
#echo off
setlocal
for /f "tokens=*" %%A in ('dir /b /s z:\Filme*.jpg') do (
if /i "%%~xf" equ ".jpg" echo %%~nxf %%~zf
) > list.txt
endlocal
Further Reading
An A-Z Index of the Windows CMD command line | SS64.com
Windows CMD Commands (categorized) - Windows CMD - SS64.com
Command Redirection, Pipes - Windows CMD - SS64.com
Dir - list files and folders - Windows CMD - SS64.com
For - Loop through command output - Windows CMD - SS64.com
If - Conditionally perform command - Windows CMD - SS64.com
Parameters / Arguments - Windows CMD - SS64.com
You know about the %%~nxA modifier, so I'm a bit surprised you didn't notice the %%~zA modifier.
To simplify it even more, use a for /R loop and don't use a temp file:
(for /R %%A in (*.jpg) do echo %%~nxA %%~zA)>list.txt
or if you need the full path\name, use %%~fA (explicite) or even just %%A
Text output:
Get-ChildItem -Path 'X:\PHOTO' -Filter '*.jp*g' -Recurse |
Where-Object {-not $_.PsIsContainer} |
Select-Object Name, Length |
Out-File -FilePath '.\FileList.txt'
CSV output:
Get-ChildItem -Path 'X:\PHOTO' -Filter '*.jp*g' -Recurse |
Where-Object {-not $_.PsIsContainer} |
Select-Object Name, Length |
Export-Csv -Path '.\FileList.csv' -NoTypeInformation
P.S. I've used *.jp*g wildcard that will also match *.jpeg files. Unfortunately, * wildcard matches zero or more symbols, so you can get files like zzz.jpXXXg in your list. There are other ways to filter Get-ChildItem output that don't suffer from this issue, such as filtering with pipeline and regex but they're slower: Where-Object {$_.Extension -match '^\.jp[e]{1}g$'}
Another option would be to not use the -Filter parameter, but the -Include instead where the wildcard pattern works as expected, like this:
PowerShell version 3.0 and up
Get-ChildItem 'z:\Filme' -File -Include '*.jpg' -Recurse |
Select FullName, Length |
Export-Csv '.\FileList.csv' -NoTypeInformation
PowerShell version below 3.0
Get-ChildItem 'z:\Filme' -Include '*.jpg' -Recurse |
Where-Object { !$_.PsIsContainer} |
Select FullName, Length |
Export-Csv '.\FileList.csv' -NoTypeInformation
Note that -Include only works if you also specify -Recurse or if you have the path end in \* like in Get-Childitem 'z:\Filme\*'.
Also, -Filter works faster than -Include (or -Exclude) parameters.
As stated in the docs:
"Filters are more efficient than other parameters, because the provider applies them when the cmdlet gets the objects. Otherwise, PowerShell filters the objects after they are retrieved."
I have never looked into the layout from the Where command, but if it does not alter between languages/locales, or technically if your layout is not too dissimilar to that of my test system, you could do it on your machine like this:
From the Command Prompt:
(For /F "Tokens=1,3*" %A In ('Where/T /R . *.jpg 2^>Nul')Do #Echo("%C","%A")>"list.txt"
From a batch file:
#(For /F "Tokens=1,3*" %%A In ('Where/T /R . *.jpg 2^>Nul')Do #Echo("%%C","%%A")>"list.txt"
Obviously if the layout from your Where command output differs there's still a possibility to adjust the Tokens and/or include delimiters to suit your target system.
In the examples above, I've used . to represent the current directory, you could of course change that to another relative path, e.g. ..\Pictures, or full path, e.g. C:\Users\Patrick\Pictures as necessary.
And a powershell option:
Ls -Filt '*.jpg' -Fo -Rec -EA SilentlyContinue|?{!$_.PSIsContainer -And $_.Extension -Eq '.jpg'}|Select FullName,Length|ConvertTo-CSV -NoT|Select -Skip 1|SC '.\list.txt'
This will also include e.g. system and hidden files, will not include files with extensions other than .jpg and will not include an unrequested header with that listing.
try this
Get-ChildItem "yourdir" -File -Filter '*.jpg' -Recurse |
Select FullName, Length |
Export-Csv '.\FileList.csv' -NoType

Ignore first line in FINDSTR search

I am searching an object-oriented Modelica library for a certain string using the following command in the Windows 7 PowerShell:
findstr /s /m /i "Searchstring.*" *.*
click for findstr documentation
The library consists of several folders containing text files with the actual code in them. To reduce the number of (unwanted) results, I have to ignore the first line of every text file.
Unfortunately, I cannot work out how to do this with the findstr command.
You can use Select-String instead of findstr
To get all matches excluding the ones on the first line try something like this:
Select-String -Path C:\dir\*.* -pattern "Searchstring*" | where {$_.LineNumber -gt 1}
If you have to search subdirectories you can pair it with Get-Childitem:
Get-Childitem C:\dir\*.* -recurse | Select-String -pattern "Searchstring*" | where {$_.LineNumber -gt 1}
If you want to keep using findstr you could simply pipe the output into Select-Object:
findstr /s /m /i "Searchstring.*" *.* | select -Skip 1

What is the equivalent of »dir /s /b *foo*.docx« in powershell

I am looking for the powershell equivalent for cmd.exe's
dir /s /b *foo*.docx
I'd like to create an alias (or scriptlet?) for this.
I have found How do I do 'dir /s /b' in PowerShell? but with this approach I seem unable to pass the argument *foo*.docx.
As stated in my comment above, you're looking for:
gci -recurse -filter *foo*.docx | select -expandproperty fullname
gci or Get-ChildItem will return a list of file system objects that match the filter you specified. Each object will have a whole load of information attached with it, but as you're only interested in the path, you can just take the fullname property by piping to select as shown. The -expandproperty flag will ensure the result is returned as a string array rather than a list of objects.
Get-ChildItem -Recurse -Filter *foo*.docx | Select-Object FullName | Sort-Object Length

Concatenate files using PowerShell

I am using PowerShell 3.
What is best practice for concatenating files?
file1.txt + file2.txt = file3.txt
Does PowerShell provide a facility for performing this operation directly? Or do I need each file's contents be loaded into local variables?
If all the files exist in the same directory and can be matched by a simple pattern, the following code will combine all files into one.
Get-Content .\File?.txt | Out-File .\Combined.txt
I would go this route:
Get-Content file1.txt, file2.txt | Set-Content file3.txt
Use the -Encoding parameter on Set-Content if you need something other than ASCII which is the default for Set-Content.
If you need more flexibility, you could use something like
Get-ChildItem -Recurse *.cs | ForEach-Object { Get-Content $_ } | Out-File -Path .\all.txt
Warning: Concatenation using a simple Get-Content (whether or not using -Raw flag) works for text files; Powershell is too helpful for that:
Without -Raw, it "fixes" (i.e. breaks, pun intended) line breaks, or what Powershell thinks is a line break.
With -Raw, you get a terminating line end (normally CR+LF) at the
end of each file part, which is added at the end of the pipeline. There's an option for that in newer Powershells' Set-Content.
To concatenate a binary file (that is, an arbitrary file that was split for some reason and needs to be put together again), use either this:
Get-Content -Raw file1, file2 | Set-Content -NoNewline destination
or something like this:
Get-Content file1 -Encoding Byte -Raw | Set-Content destination -Encoding Byte
Get-Content file2 -Encoding Byte -Raw | Add-Content destination -Encoding Byte
An alternative is to use the CMD shell and use
copy file1 /b + file2 /b + file3 /b + ... destinationfile
You must not overwrite any part, that is, use any of the parts as destination. The destination file must be different from any of the parts. Otherwise you're up for a surprise and must find a backup copy of the file part.
a generalization based on #Keith answer:
gc <some regex expression> | sc output
Here is an interesting example of how to make a zip-in-image file based on Powershell 7
Get-Content -AsByteStream file1.png, file2.7z | Set-Content -AsByteStream file3.png
Get-Content -AsByteStream file1.png, file2.7z | Add-Content -AsByteStream file3.png
gc file1.txt, file2.txt > output.txt
I think this is as short as it gets.
In case you would like to ensure the concatenation is done in a specific order, use the Sort-Object -Property <Some Name> argument. For example, concatenate based on the name sorting in an ascending order:
Get-ChildItem -Path ./* -Include *.txt -Exclude output.txt | Sort-Object -Property Name | ForEach-Object { Get-Content $_ } | Out-File output.txt
IMPORTANT: -Exclude and Out-File MUST contain the same values, otherwise, it will recursively keep on adding to output.txt until your disk is full.
Note that you must append a * at the end of the -Path argument because you are using -Include, as mentioned in Get-ChildItem documentation.

Merge same named .txt file in different directories?

I have a folder that is filled with sub folders of past dates (20120601 for example), inside each date folder there is a file named test.txt, along with another file named example.txt. How can I merge all the test.txt files into one?
I am trying to do this in Windows and have access to Windows PowerShell and Windows Command Processor (cmd.exe). What would be the best way to do this?
My hierarchy would look something like this:
\Data
\20120601
test.txt
example.txt
\20120602
test.txt
example.txt
\20120603
test.txt
example.txt
\20120604
test.txt
example.txt
\20120605
test.txt
example.txt
I would imagine it is something like
copy *\test.txt alltestfiles.txt
Is that possible? Can you specify a wildcard for a directory?
Fairly easy, actually:
Get-ChildItem \Data -Recurse -Include test.txt |
Get-Content |
Out-File -Encoding UTF8 alltestfiles.txt
or shorter:
ls \Data -r -i test.txt | gc | sc -enc UTF8 alltestfile.txt
This will first gather all test.txt files, then read their contents and finalle write out the combined contents into the new file.
List all the files. Read one file's content and add it into the combined file. Like so,
cd data
gci -Recurse | ? { -not $_.psIsContainer -and $_.name -like "test.txt"}
$files | % { Add-Content -Path .\AllTests.txt -Value (Get-Content $_.FullName) }
A simple command like cat path\**\* > target_single_file also works.