file operations and search recipes

See also: all the recipes and the intro

 # find all the files *.txt recursively under a directory, like Unix find
dir /s /a dir\*.txt
# in PowerShell
dir -Recurse -Force "dir\*.txt"

# search for text in the files, like find -exec grep
# /s is recursive, /r is regexp, /i is ignore-case
findstr /s /r /i string dir\*.txt
# for a string that contains multiple words
findstr /s /r /c:"string" dir\*.txt

# The find-grep in PowerShell
dir -Recurse *.cs | % { $res = @((type $_) -match "QueryInstances"); if ($res) { $res; $_.FullName } }
# replace the strings in many files
dir -Recurse run.psm1 | % { $t = type $_.FullName; $t | % { $_ -Replace "Write-Verbose","Write-Dual" } | Set-Content $_.FullName; echo $_.FullName }

# PowerShell: compute the space used the straight way (this rounds up the space used by file to at least 1KB)
dir -recurse . | % { ($_.Length + 1023) / 1024 } | measure -Sum
 # find if trim is supported
fsutil fsinfo sectorinfo c:

# find the hardlinks of a filename
fsutil hardlink list filename

# function to ignore the hard links
function dedup
{
    param(
        [Parameter(ValueFromPipeline = $true, Mandatory=$true)]
        $f
    )
    begin { $t = @{} }
    process {
        $n =@(fsutil hardlink list $f.FullName)[0];
        if (!$t.Contains($n)) {$t[$n] = 1; $f; }
    }
}

# resizing a VHD image
Resize-VHD -Path C:\vm\nano\10119\nanoServerResize.vhd -SizeBytes 127GB
# resizing without PowerShell
diskpart: diskpart /s scriptfile select vdisk
file="C:\vm\nano\10119\nanoServerResize.vhd"
# instead of Resize-Vhd 127GB: expand vdisk maximum=130048
attach vdisk select partition=1 extend extend filesystem
# to mount
assign letter=w
# to unmount
detach vdisk offline disk

# how to remove the unused blocks (compact) on a VHD (it must be unmounted)
# from
# https://blogs.technet.com/b/askcore/archive/2012/09/20/compacting-a-dynamically-expanding-virtual-hard-disk-in-windows-server-2012.aspx
Optimize-Vhd -path <full path the vhd file> -Mode Full
 # not a recipe as such but related...
function relname
{
<#
.SYNOPSIS
Convert the absolute file names on input to the relative file names
by removing the common directory prefix.

.INPUT
The file names (or FileInfo/DirectoryInfo, or any objects that have
a field .FullName) to be converted to the relative path names.

.OUTPUT
The same names after removing the common prefix.
#>
    param(
        ## The root directory, relative to which the input files should be named.
        [string] $Root = "."
    )
    begin {
        $Root = (Get-Item $Root).FullName
        $rpat = "^" + [regex]::Escape($Root) + "\\?"
    }
    process {
        if ($_ -is [string]) {
            $f = $_
        } else {
            $f = $_.FullName
        }
        $f -replace $rpat,""
    }
}