9

I'd like to find and copy all the files in a certain directory and all it's sub-directories with a particular name.

I'm using Copy-Item in Powershell (technet | ss64)

Here's what I have:

Copy-Item `
    -Path \\Server\Apps\* `
    -Destination C:\ReadMeFiles\ `
    -Include *ReadMe.txt `
    -Recurse `
    -WhatIf

It will grab the following file:

\\Server\Apps\ReadMe.txt

But not:

\\Server\Apps\AppName\ReadMe.txt

Even though I've specified -recurse

How can I get it to travel down in each directory?

4
  • 1
    Why \\Server\Apps\* and not \\Server\Apps?
    – Dan
    Commented Mar 24, 2015 at 19:04
  • You didn't provide it a file extension ( i.e. Path \\Server\Apps*.* ). Existing Question
    – Ramhound
    Commented Mar 24, 2015 at 19:04
  • @Ramhound & @Dan, neither changes are finding subdirectories inside of `Apps`
    – KyleMit
    Commented Mar 24, 2015 at 19:09
  • @KyleMit - Hopefully you corrected the typo that I had made.
    – Ramhound
    Commented Mar 25, 2015 at 10:42

2 Answers 2

7

My slightly modified answer from this question: Batch File:List all files of a type, rename files, flatten the directory

It does what you want: copies files using wildcard, flattens directory structure, handles filename conflicts. It uses Get-ChildItem, as Tᴇcʜιᴇ007 suggested.

# Setup source and destination paths
$Src = '\\Server\Apps'
$Dst = 'C:\ReadMeFiles'

# Wildcard for filter
$Extension = '*ReadMe.txt'

# Get file objects recursively
Get-ChildItem -Path $Src -Filter $Extension -Recurse |
    # Skip directories, because XXXReadMe.txt is a valid directory name
    Where-Object {!$_.PsIsContainer} |
        # For each file
        ForEach-Object {

            # If file exist in destination folder, rename it with directory tag
            if(Test-Path -Path (Join-Path -Path $Dst -ChildPath $_.Name))
            {
                # Get full path to the file without drive letter and replace `\` with '-'
                # [regex]::Escape is needed because -replace uses regex, so we should escape '\'
                $NameWithDirTag = (Split-Path -Path $_.FullName -NoQualifier)  -replace [regex]::Escape('\'), '-'

                # Join new file name with destination directory
                $NewPath = Join-Path -Path $Dst -ChildPath $NameWithDirTag
            }
            # Don't modify new file path, if file doesn't exist in target dir
            else
            {
                $NewPath = $Dst
            }

            # Copy file
            Copy-Item -Path $_.FullName -Destination $NewPath
        }
8

It's a known issue with Copy-Item, you can't specify a Wildcard in the source, and use Recurse (and have it work as you expect).

If you don't mind also copying the folder structure (yet only copying the readme's) try using the "Filter" option. Something like:

Copy-Item \\Server\Apps\ C:\ReadMeFiles\ -Filter *ReadMe.txt -Recurse

Alternatively you may be able to use Get-Child-Item with Recurse, and a For loop to feed Copy-Item the files one at a time.

1
  • Thanks! Yeah, I'm doing this to flatten all the files out of a directory structure, so I'll probably have to use Get-Childitem and pipe into Copy-Item.
    – KyleMit
    Commented Mar 24, 2015 at 19:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .