PowerShell Output Filenames of a Specific Extension to a Text File - windows

Currently, I'm using the following command to output filenames to a text file:
( Get-ChildItem -File ).BaseName | Out-File "Track List.txt" -Encoding utf8
How can I limit the filenames to a specific extension, e.g., .mp3?

The -Filter paramater accepts wildecards - ? for any single character, and * for zero or more matches
( Get-ChildItem -File -Filter *.mp3).BaseName | Out-File "Track List.txt" -Encoding utf8
See the Powershell documentaiton on -Filter and wildcards for more information
[wildcards]:

Related

How to rename multiple files with existing Unix time in file name?

While I know how I would do this in PHP, it doesn't make sense to install IIS, install PHP just to get this done.
I have a folder D:\Data that has several subfolders in it. These folders contain files which are backups created with a program that adds a time stamp to the name to allow multiple copies of the file to be backed up.
These files need to be named:
usera.dat
But they are named currently:
usera.dat.17383947323.dat
In PHP, I would load the file name into a string, explode the string on ".", then rename the file using the [0] and [3] elements to rename the file, i.e. without the loop to read the directories:
$filename = $existing_file
$explodename = explode(".",$filename);
$newfilename = $explodename[0] . "." . $explodename[3];
rename($filename, $newfilename);
Does anyone have any recommendation on how to do this with PowerShell or a batch file looping over all the subfolders in D:\Data?
Right now I am manually editing each file removing the extra Unix time stamp.dat part.
Translating this from PHP to PowerShell should be a breeze, let's give it a try:
$files = Get-ChildItem -Filter *.dat.*.dat
foreach($file in $files){
$filename = $file.Name
$explodename = $filename.Split('.')
$newfilename = "$($explodename[0]).$($explodename[3])"
Rename-Item $file.FullName -NewName $newfilename
}
As shown above:
PowerShell does not have an explode() function, but we can use the String.Split() method on any string and get a string array back
. is not a string concat operator in PowerShell, but we can use subexpressions $(...) inside an expandable string.
The Rename-Item cmdlet will take care of renaming
A more PowerShell-idiomatic solution would be to leverage the pipeline though:
Get-ChildItem -Filter *.dat.*.dat | Rename-Item -NewName {$explodename = $_.Name.Split('.');"$($explodename[0]).$($explodename[3])"}
You could also use a regex pattern in place of the Split() method and string concatenation:
Get-ChildItem -Filter *.dat.*.dat | Rename-Item -NewName {$_.Name -replace '^([^\.])\..*\..*\.([^\.])$','$1.$2'}
Or do the concatenation with the -join operator:
Get-ChildItem -Filter *.dat.*.dat | Rename-Item -NewName {$_.Name.Split('.')[0,3] -join '.'}
Whatever you fancy, Get-ChildItem and Rename-Item are definitely the commands you'd want to use here
One-liner in batch from the prompt:
#FOR /r "U:\sourcedir" %a IN (*) DO #FOR %b IN ("%~na") DO #FOR %c IN ("%~nb") DO #IF "%~xc" neq "" ECHO REN "%a" "%~nxc"
Note: echoes the rename command for testing. Remove the echo keyword after testing to execute the rename.
I used u:\sourcedir as a test directory.
Translation: for each filename in the subtree (%%a) take the name part only and assign to %%b, repeat for %%c and if there was no extension part in the result, then do the rename.
Mathias R. Jessen's answer contains many helpful pointers, but it seems that the simpler and more robust approach would be to simply drop the final 2 extensions, assuming that all files in the folder tree have these 2 extraneous extensions:
Get-ChildItem -File -Recurse D:\Data |
Rename-Item -NewName { $_.Name -replace '(\.[^.]*){2}$' }

How to pipeline batch script output to a PowerShell script?

I need to use HTTP Apache piped logging to place all entries with response code "400" into a separate file. For that, I want to use PowerShell Select-String since it is the closest thing to the grep command in Linux:
I have the following batch to call a PowerShell script from within a cmd environment:
powershell -command "& { sls ,400, 'cmd -ca | select -exp line >> access_400.log }"
As far as I know, the "CustomLog" in httpd will be similar to this:
CustomLog "| 'call_powershell_script_that_will_extract_400_entries.ps1' " common
How can I make the piped output of CustomLog be input to the PowerShell script that will extract the entries with "400" response code?
Use the automatic PowerShell variable, $input, in your script.
I don't totally understand your script, but you should be able to extrapolate this similar example:
filter.bat
#powershell -command "$input | select-string -casesensitive -pattern '%1' | select-object -expandproperty line | out-file -append -encoding ASCII output.log"
$input will be filled with the console input for the BAT/CMD file.
To test, from the command line, use dir | filter.bat ".exe", then type output.log.
Notably, I'm using out-file instead of the powershell redirection operator so that the output file is not encoded in the powershell default, UTF-16, but as a more generally usable ASCII file.

Bigger txt file with less rows on Windows after Powershell Select-String

I applied several filters to a text files using Powershell Get-Content and the -nomatch operator and then i spooled the result to a file.
gc file.txt | {?_ -notmatch 'excl1|excl2|excl3'} | out-file newfile.txt
What happens is that the output file (newfile.txt) has less lines, but it is reported by windows with a bigger size than file.txt.
Has someone ever encountered this behavior? How can I have the correct size reported by windows? I checked the number of rows, the file with less rows is reported as bigger in size.
I'm certain you have an encoding issue. By default Get-Content uses ascii whereas Out-File uses Unicode.
From TechNet
-Encoding
Specifies the type of character encoding used in the file. Valid values are "Unicode", "UTF7", "UTF8", "UTF32", "ASCII", "BigEndianUnicode", "Default", and "OEM". "Unicode" is the default.
Use -Enconding ascii with Out-File or just use Set-Content as it is the partner of Get-Content.
Get-Content file.txt | {?_ -notmatch 'excl1|excl2|excl3'} |
out-file -Encoding ascii newfile.txt
# or
Set-Content newfile.txt
Coming from the other direction if you have issues with your input file Get-Content in PowerShell v3 and above also supports -Enconding

Windows : How to list files recursively with size and last access date?

I need a simple way to create a list of all files in a certain folder. (recursively)
Each file must be in a single line. I also need the file size and the last access date in the same line, separated by a special character.
The output (textfile) should look like this:
c:\folder\file1.txt|400|2012-11-12 15:23:08
c:\folder\file2.txt|200|2012-11-12 15:23:08
c:\folder\file3.txt|100|2012-11-12 15:23:08
c:\folder\sub folder\file4.txt|500|2012-11-12 15:23:08
'Dir' seems not to be an option, because the German Special characters get messed up that way. (öäüß)
Powershell handles the special characters well, but I couldn't make it so that the information for one file ends up in a single line:
get-childitem D:\temp -rec | where {!$_.PSIsContainer} | foreach-object -process {$_.FullName, $_.LastWriteTime, $_.Length}
try this:
get-childitem D:\temp -rec | where {!$_.PSIsContainer} |
select-object FullName, LastWriteTime, Length | export-csv -notypeinformation -delimiter '|' -path file.csv

Command or Script to rename multiple files in windows

I have around 400 movies on my hard-disk, but names of those movies contains dots or underscore in between like "wrong_turn.mkv" or "wrong.turn.mkv". I just want to remove these dots or special characters from the file name and keep the extension as it as.
Any Command Line command or Powershell/Python or any other script for windows? Thanks.
If the two files you have reside in the same directory then removing _ from the first file will work, but when you'll try to remove the dot from the second file it will fail cause it'll have the same name as the first one. Maybe that's an edge case, so here's the basic solution:
Get-ChildItem -Filter *.mkv | Rename-Item -NewName {($_.BaseName -replace '\.|_') + $_.Extension}
In PowerShell you can use Rename-Item with a script block that determines the new name.
dir -Recurse -Include *.mkv | Rename-Item -NewName { expression to determine new name }
The expression within the script block can use $_ to reference the current FileInfo object.
More concretely:
dir -Recurse -Include *.mkv | Rename-Item -NewName { $_.Name.Replace('_', ' ') }
Use Rename-Item -WhatIf until you get it right.

Resources