2

I have been tasked to sort home video and pictures for my family. The scripts that I have work fine but I have to manually run them against each directory. How can I run my script against all child-items that are only at 1 Depth?

My current crude scripts are as follows:

$current_dir = Split-Path -Path $pwd -Leaf
$new_path = "H:\sorted\$current_dir\pictures"

Get-ChildItem -R . -Include ('*.jpg', '*.jpeg', '*.png') | Move-Item -Destination (New-Item -Force -Path "$new_path" -Type Directory)
$current_dir = Split-Path -Path $pwd -Leaf
$new_path = "H:\sorted\$current_dir\videos"

Get-ChildItem -R . -Include ('*.mp4', '*.mkv', '*.3pg','*.flv', '*.mov', '*.gif') | Move-Item -Destination (New-Item -Force -Path "$new_path" -Type Directory)

Example file tree

E:.
├───April9383
├───April98765
│   └───carson
├───Cathy
├───Cathy(1)
├───Charlie
│   ├───Photos
│   └───Videos
├───daleville

I want the end structure to look like Charlie does in the example. How can I run both of these with a loop from E: ?

I have tried

$sub_dir = $(Get-ChildItem . -Depth 1)

foreach ($sub in $sub_dir)  {
    picture-sort.ps1
}

but this took the name of the folder that all of the example files were stored in and not that of "April9383" etc

SOLVED:

I ended up going with @Santiago's response but edited a bit as it wasn't working exactly how I needed it.

I took this and ran with it to end up with

$base = "E:\sorted"
$current_dir = $pwd
# get the folders 1 level deep and enumerate
Get-ChildItem . -Depth 0 -Directory | ForEach-Object {
    # join the destination with this folder's Name
    $path = Join-Path $base -ChildPath $_.Name
    $pic_path = "$path\pictures"
    $vid_path = "$path\videos"
    
    #source dirs
    $stripped_dest_path = Split-Path -Path $path -Leaf
    $src_path = Join-Path $current_dir  $stripped_dest_path 
    
    #Print statement
    Write-Output "Copying pictures from $src_path to $pic_path"
    # get and move all pictures
    Get-ChildItem -R $src_path -Include ('*.jpg', '*.jpeg', '*.png') |
        Copy-Item -ErrorAction SilentlyContinue -Destination (New-Item -Force -Path "$pic_path" -Type Directory)

    #Print statement
    Write-Output "Copying videos from $src_path to $vid_path"
    # get and move all videos
    Get-ChildItem -R $src_path -Include ('*.mp4', '*.mkv', '*.3pg','*.flv', '*.mov', '*.gif', '*.avi') |
        Copy-Item -ErrorAction SilentlyContinue -Destination (New-Item -Force -Path "$vid_path" -Type Directory)


    Write-Output "END OF LOOP"
}

3 Answers 3

3

You're almost there, just need to put all your logic inside the loop:

$base = "H:\sorted"
# get the folders 1 level deep and enumerate
Get-ChildItem . -Depth 1 -Directory | ForEach-Object {
    # join the destination with this folder's Name
    $path = Join-Path $base -ChildPath $_.Name

    # get and move all pictures
    $_ | Get-ChildItem -Recurse -Include '*.jpg', '*.jpeg', '*.png' |
        Move-Item -Destination (New-Item -Path (Join-Path $path -ChildPath 'Pictures') -Type Directory -Force)

    # get and move all videos
    $_ | Get-ChildItem -Recurse -Include '*.mp4', '*.mkv', '*.3pg','*.flv', '*.mov', '*.gif' |
        Move-Item -Destination (New-Item -Path (Join-Path $path -ChildPath 'videos') -Type Directory -Force)
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks this somewhat worked but I had to remove $_ | from both picture and video lines or else it added everything to the pictures folder including old, empty directories from the source. edit: nevermind, this is just adding copies to everything in the new folders that are created
1

I ended up going with @Santiago's response but edited a bit as it wasn't working exactly how I needed it.

I took this and ran with it to end up with

$base = "E:\sorted"
$current_dir = $pwd
# get the folders 1 level deep and enumerate
Get-ChildItem . -Depth 0 -Directory | ForEach-Object {
    # join the destination with this folder's Name
    $path = Join-Path $base -ChildPath $_.Name
    $pic_path = "$path\pictures"
    $vid_path = "$path\videos"
    
    #source dirs
    $stripped_dest_path = Split-Path -Path $path -Leaf
    $src_path = Join-Path $current_dir  $stripped_dest_path 
    
    #Print statement
    Write-Output "Copying pictures from $src_path to $pic_path"
    # get and move all pictures
    Get-ChildItem -R $src_path -Include ('*.jpg', '*.jpeg', '*.png') |
        Copy-Item -ErrorAction SilentlyContinue -Destination (New-Item -Force -Path "$pic_path" -Type Directory)

    #Print statement
    Write-Output "Copying videos from $src_path to $vid_path"
    # get and move all videos
    Get-ChildItem -R $src_path -Include ('*.mp4', '*.mkv', '*.3pg','*.flv', '*.mov', '*.gif', '*.avi') |
        Copy-Item -ErrorAction SilentlyContinue -Destination (New-Item -Force -Path "$vid_path" -Type Directory)


    Write-Output "END OF LOOP"
}

Comments

0

This should work:

$PictureFiles = @('*.jpg', '*.png')
$VideoFiles = @('*.mkv', '*.mp4')

$MyFiles = Get-ChildItem H:\sorted -Recurse -File -Include @($PictureFiles + $VideoFiles) -Depth 1

foreach ($File in $MyFiles) {
    #Videos
    if ($File.Extension -in ($VideoFiles -replace '\*')) {
        mkdir ($File.DirectoryName + "\Videos\") -Force
        Move-Item -Path $File.FullName -Destination ($File.DirectoryName + "\Videos\" + $File.Name) -Force
    }

    #Pictures
    if ($File.Extension -in ($PictureFiles -replace '\*')) {
        mkdir ($File.DirectoryName + "\Pictures\") -Force
        Move-Item -Path $File.FullName -Destination ($File.DirectoryName + "\Pictures\" + $File.Name) -Force
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.