1

As different apps require different file names, I have been trying to copy Folder.jpg to cover.jpg in all subfolders but couldn't get my shellscript to work.

get-childItem -recurse | Where {$_.extension -eq "jpg"} | copy-item Folder.jpg cover.jpg

There was no error but nothing happened.

Grateful for any help from the experts here.

Sven
  • 98,649
  • 14
  • 180
  • 226
Jacky
  • 11
  • 1
  • 2
  • It's unclear from your question where Folder.jpg is located. If there is nothing to pipe the latter commands aren't executed. Also you have two parameters to the copy **and** piped input? – LotPings Apr 26 '17 at 16:31
  • Folder.jpg (different contents) is in all the subdirectories. I wanted to transverse all the subdirectories and copy any Folder.jpg to cover.jpg. – Jacky Apr 26 '17 at 17:34

2 Answers2

1

It's easiest to recursively search for Folder.jpg, change into that folder, copy and get the next one.

# Change to base folder
Push-Location "Q:\Test\2017"
Get-ChildItem Folder.jpg -Recurse | ForEach-Object {
  Set-Location $_.DirectoryName
  Copy-Item .\Folder.jpg .\Cover.jpg
} 
Pop-Location

gci folder.jpg -r|copy -dest {$_.FullName -replace 'folder','cover'}
LotPings
  • 1,015
  • 7
  • 12
  • Hi @LotPings, finally had time to work on the actual drive. But I got the error message that Folder.jpg not found on root drive. After I added a dummy Folder.jpg to try out, it copied Folder.jpg to cover.jpg at root but didn't go down to any sub-directories. No error message. Xalorous' one liner seems to work better though his is practically the same. – Jacky May 18 '17 at 04:12
  • What exact folder did you choose with Push-Location ? Try `Get-ChildItem .\Folder.jpg ...` – LotPings May 19 '17 at 10:20
  • just the root directory, in my case G:\ – Jacky May 21 '17 at 11:23
  • Just did a test and don't get that behaviour. Just appended another one liner to my answer. – LotPings May 21 '17 at 11:51
0

@LotPings has shown a nicely formatted PS script for your task. It would be even better if it was a function.

function Copy-Covers ($location) {
    # Change to base folder
    Push-Location $location

    # Recursively copy all occurrences of folder.jpg under $location
    Get-ChildItem Folder.jpg -Recurse | ForEach-Object {
      Set-Location $_.DirectoryName
      Copy-Item .\Folder.jpg .\Cover.jpg
    } 
    Pop-Location

}

For a one-time task, you can often use one-liners. In this case, it would look like this (execute from base folder where you want the copying to take place):

gci -R -filter folder.jpg | % {copy $_ "$($_.DirectoryName)\cover.jpg" }
Jeter-work
  • 845
  • 4
  • 15
  • Hi @Xalorous, thanks for the one-liner and it does work better. But it seems to have problem when a folder name contains square brackets. Error message. Copy-Item : Cannot retrieve the dynamic parameters for the cmdlet. The specified wildcard pattern is not valid: Bruckne r - Symphony No. 7 in E Major [Karajan-Wiener] At line:1 char:36 – Jacky May 18 '17 at 03:26
  • So the command did 80% of the work except those folders containing []. – Jacky May 18 '17 at 03:29
  • The brackets probably need special handling. On systems I administer, I solve this by not using brackets. :) But I understand that in your use case they're already there. My suggestion is to use the core command, `Get-ChildItem`, and use it to parse the folder structure. Locate the type of folder that is giving you the problem, and try to find a way to get that folder name in a way you can use. All string properties have a method you can use on them called `.replace()`. You may be able to do something like `$file.DirectoryName = $file.DirectoryName.replace('[','/[').replace(']','/]')` – Jeter-work May 19 '17 at 21:13
  • At this point, I'd suggest posting a question in stack overflow, with the oneliner you used, and a paste of the error message, and ask how to handle folder names with brackets. Some of the PS guys there are amazing. – Jeter-work May 19 '17 at 21:14
  • Thanks. I did a bit of digging and found that [] are wild cards in Powershell and removing them is quite tedious from the postings I found. – Jacky May 21 '17 at 11:16
  • ,by the way, your one-liner didn't quite do the copying which it should. I made a minor change (try and error) and it worked: gci -R -filter folder.jpg | % {copy "$($_.DirectoryName)\Folder.jpg" "$($_.DirectoryName)\cover.jpg" } I don't understand much of the intricacies in Powershell - just wanted to do a quick and dirty for this one-off job. – Jacky May 21 '17 at 11:17
  • There is a property of each file which includes the full path and file name (`.fullname`). The reason it doesn't work is that $_ in the second part of the oneliner, is just the name of the file. In many instances, PowerShell treats the object as an object. In this case it's giving us just one property of the object. Another way to do what you did is `$_.fullname` instead of `"$($_.DirectoryName)\Folder.jpg"`. First it's shorter and easier to type, second it's less hard-coded. But I'm glad you got it to work. – Jeter-work May 25 '17 at 23:55