6

So, the folder structure looks like this:

  1. SourceFolder
    • file1.txt
    • file1.doc
      1. Subfolder1
        • file2.txt
        • file2.doc
          1. SubSubFolder
            • file3.txt
            • doc3.txt

What I want to do is copy all .txt files from folders, whose (folder) names contains the eng, to a destination folder. Just all the files inside the folder - not the file structure.

What I used is this:

$dest = "C:\Users\username\Desktop\Final"
$source = "C:\Users\username\Desktop\Test1"
Copy-Item $source\eng*\*.txt $dest -Recurse

The problem is that it copies the .txt files only from each parent folder but not the sub-folders.

How can I include all the sub-folders in this script and keep the eng name check as well? Can you please help me?

I am talking about PowerShell commands. Should I use robocopy instead?

arco444
  • 22,002
  • 12
  • 63
  • 67
John Enxada
  • 95
  • 1
  • 1
  • 4

5 Answers5

9

Yet another PowerShell solution :)

# Setup variables
$Dst = 'C:\Users\username\Desktop\Final'
$Src = 'C:\Users\username\Desktop\Test1'
$FolderName = 'eng*'
$FileType = '*.txt'

# Get list of 'eng*' file objects
Get-ChildItem -Path $Src -Filter $FolderName -Recurse -Force |
    # Those 'eng*' file objects should be folders
    Where-Object {$_.PSIsContainer} |
        # For each 'eng*' folder
        ForEach-Object {
        # Copy all '*.txt' files in it to the destination folder
            Copy-Item -Path (Join-Path -Path $_.FullName -ChildPath '\*') -Filter $FileType -Destination $Dst -Force
        }
beatcracker
  • 6,714
  • 1
  • 18
  • 41
  • Thank for the PS script, it worked well. Comments were really helpful as well. – John Enxada Mar 26 '15 at 17:17
  • @JohnEnxada You're welcome. Check this answer also (more advanced script, handles filename conflicts): http://superuser.com/a/894220/418201 Can't filter by folder name though, but you can rip filename checking code from there if you need. – beatcracker Mar 26 '15 at 20:20
1

You can do this :

$dest = "C:\NewFolder"
$source = "C:\TestFolder"
$files = Get-ChildItem $source -File -include "*.txt" -Recurse | Where-Object { $_.DirectoryName -like "*eng*" }
Copy-Item -Path $files -Destination $dest
Mathieu Buisson
  • 1,325
  • 10
  • 8
1

Another take:

$SourceRoot = <Source folder path>
$TargetFolder = <Target folder path>


@(Get-ChildItem $SourceRoot -Recurse -File -Filter *.txt| Select -ExpandProperty Fullname) -like '*\eng*\*' |
foreach {Copy-Item $_ -Destination $TargetFolder}
mjolinor
  • 66,130
  • 7
  • 114
  • 135
0

Fine to do that with powershell. Try:

$dest = "C:\Users\username\Desktop\Final"
$source = "C:\Users\username\Desktop\Test1"

Get-ChildItem $source -filter "*.txt" -Recurse | Where-Object { $_.DirectoryName -match "eng"} | ForEach-Object { Copy-Item $_.fullname $dest }
arco444
  • 22,002
  • 12
  • 63
  • 67
  • Thank you! It works but partially. There is no check for the *eng* on the folder names. Can you please help me on this as well? – John Enxada Mar 17 '15 at 13:53
  • Be careful with this one. It will match any file that contains "eng" anywhere in the file path. Any of the following would match: C:\eng\file.txt, C:\lengend\file.txt, C:\directory\file-eng.txt, etc. – New Guy Mar 17 '15 at 13:56
  • To clarify, my above comment was only if $source is equal to C:\. My examples used C:\ as the root for brevity but the issue is the same regardless. – New Guy Mar 17 '15 at 14:08
  • @JohnEnxada updated. There is a check to see if the directory name of the file includes `eng`. As "New Guy" points out, that could appear anywhere in the tree, but as you are setting your source directory it shouldn't be an issue here – arco444 Mar 17 '15 at 14:11
  • @arco444 The issue could still occur. Here are some examples that would match given the source the OP has specified: C:\Users\username\Desktop\Test1\english\file.txt, C:\Users\username\Desktop\Test1\eng\file.txt, C:\Users\username\Desktop\Test1\bioengineering\file.txt It may be the case the OP doesn't have to worry about that as the filenames may be consistent and well known. However, users and admins have a tendency to create inconsistencies. It is probably best to look at each folder's BaseName and make sure it starts with `eng` rather than being in the middle or end of the name. – New Guy Mar 17 '15 at 15:39
  • @NewGuy where did OP mention it had to *start* with `eng`? He just said contiains. Given he specifies a base directory, only those below it that contain `eng` will be matched, exactly the same as in your answer. – arco444 Mar 17 '15 at 15:42
  • @arco444 The OPs example implies that it needs to start with `eng`. `Copy-Item $source\eng*\*.txt $dest -Recurse` – New Guy Mar 17 '15 at 15:55
  • @NewGuy Fair point, the snippet says that, the description doesn't. Well I guess there's enough information here for him to make his own decision! – arco444 Mar 17 '15 at 16:09
0

It may be easier to first get a list of all the folders that contain eng in the name.

$dest = "C:\Users\username\Desktop\Final"
$source = "C:\Users\username\Desktop\Test1"

$engFolders = Get-ChildItem $source -Directory -Recurse | Where { $_.BaseName -match "^eng" }
Foreach ($folder In $engFolders) {
    Copy-Item ($folder.FullName + "\*.txt") $dest
}
New Guy
  • 8,606
  • 1
  • 15
  • 12