user1238528
user1238528

Reputation: 175

How to modify my powershell script to search for all jpg/jpeg on a machine

I am working on building a PowerShell script that will find all the jpeg/jpg files on a machine. This is what I have so far-

# PowerShell script to list the DLL files under the C drive
$Dir = get-childitem C:\ -recurse
# $Dir |get-member
$List = $Dir | where {$_.extension -eq ".jpg"}
$List |ft fullname |out-file C:\Users\User1\Desktop\dll.txt
# List | format-table name

The only problem is that some of the files I am looking for don't have the extension jpg/jpeg. I know that you can look in the header of the file and if it says ÿØÿà then it is a jpeg/jpg but I don't know how to incorporate this into the script.

Any help would be appreciated. Thanks so much!

Upvotes: 1

Views: 9271

Answers (6)

fall
fall

Reputation: 1202

How about this one?

jp*g is used to match both jpg and jepg images.

$List = Get-ChildItem "C:\*.jp*g" -Recurse
$List |ft fullname |out-file C:\Users\User1\Desktop\dll.txt

Upvotes: 0

Jake H
Jake H

Reputation: 1740

I would recommend querying the windows search index for the jpegs, rather than trying to sniff file contents. Searching the system index using filenames is insanely fast, the downside is that you must search indexed locations.

I wrote a windows search querying script using the windows sdk \samples\windowssearch\oledb, you would want to query using the imaging properties. However, I'm not certain off the top of my head if the search index uses the imaging api to look at unknown files or files without extensions. Explorer seems to know my jpeg thumbnails and metadata without jpg extensions, so I'm guessing the indexer is going to be as clever as explorer.

Upvotes: 1

Lance U. Matthews
Lance U. Matthews

Reputation: 16612

The following will retrieve files with either a .jpg/.jpeg extension or that contain a JPEG header in the first four bytes:

[Byte[]] $jpegHeader = 255, 216, 255, 224;

function IsJpegFile([System.IO.FileSystemInfo] $file)
{
    # Exclude directories
    if ($file -isnot [System.IO.FileInfo])
    {
        return $false;
    }

    # Include files with either a .jpg or .jpeg extension, case insensitive
    if ($file.Extension -match '^\.jpe?g$')
    {
        return $true;
    }

    # Read up to the first $jpegHeader.Length bytes from $file
    [Byte[]] $fileHeader = @(
        Get-Content -Path $file.FullName -Encoding Byte -ReadCount 0 -TotalCount $jpegHeader.Length
    );

    if ($fileHeader.Length -ne $jpegHeader.Length)
    {
        # The length of the file is less than the JPEG header length
        return $false;
    }

    # Compare each byte in the file header to the JPEG header
    for ($i = 0; $i -lt $fileHeader.Length; $i++)
    {
        if ($fileHeader[$i] -ne $jpegHeader[$i])
        {
            return $false;
        }
    }

    return $true;
}

[System.IO.FileInfo[]] $jpegFiles = @(
    Get-ChildItem -Path 'C:\' -Recurse `
        | Where-Object { IsJpegFile $_; }
);

$jpegFiles | Format-Table 'FullName' | Out-File 'C:\Users\User1\Desktop\dll.txt';

Note that the -Encoding and -TotalCount parameters of the Get-Content cmdlet are used to read only the first four bytes of each file, not the entire file. This is an important optimization as it avoids basically reading every byte of file data on your C: drive.

Upvotes: 3

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200453

This should give you all files starting with the sequence "ÿØÿà":

$ref = [byte[]]@(255, 216, 255, 224)

Get-ChildItem C:\ -Recurse | ? { -not $_.PSIsContainer } | % {
  $header = [System.IO.File]::ReadAllBytes($_.FullName)[0..3]
  if ( (compare $ref $header) -eq $null ) {
    $_.FullName
  }
} | Out-File "C:\Users\User1\Desktop\dll.txt"

Upvotes: 2

malgca
malgca

Reputation: 2947

To find if the header starts with ÿØÿà, use:

[System.String]$imgInfo = get-content $_ # where $_ is a .jpg file such as "pic.jpg"
if($imgInfo.StartsWith("ÿØÿà"))
{
      #It's a jpeg, start processing...
}

Hope this helps

Upvotes: 1

Christopher Douglas
Christopher Douglas

Reputation: 1550

I'm not sure how to use powershell native commands to Look at file headers, I will do some research on it because it sounds fun. Until then I can suggest a shorter version of your initial command, reducing it to a one liner.

Get-ChildItem -Recurse -include *.jpg | Format-table -Property Fullname | Out-file C:\Users\User1\Desktop\Jpg.txt

or

ls -r -inc *.jpg | ft Fullname

EDITED: removed redundant code, thanks @nick.

I'll let you know what I find if I find anything at all.

Chris

Upvotes: 3

Related Questions