1

When using powershell to rename files with their directory name and file name, my code works, except in the first file in a directory, it gives it two copies of the directory name. So the file book1.xlsx in folder folder1 should become folder1book1.xlsx but it becomes folder1folder1book1.xlsx. The remaining files in folder1 are correctly named folder1book2.xlsx, folder1book3.xlsx, etc.

I have a directory, with many sub-directories. In each sub-dir are files that need their sub-dir name added in.

I've been following this code. For me it looks like:

dir -Filter *.xlsx -Recurse | Rename-Item -NewName {$_.Directory.Name + "_" + $_.Name}

I've also tried

--setting the Recurse -Depth 1 so that it doesn't keep looking for folders in the sub-folders.

--using ForEach-Object {$_ | ... after the pipe, similar to this.

--running it in Visual Studio Code rather than directly in PowerShell, which turns it into:

Get-ChildItem "C:\my\dir\here" -Filter *.xls -Recurse | Rename-Item -NewName {$_.DirectoryName + '_' + $_.Name}

--putting an empty folder inside the sub-directory, setting -Depth 2 to see if that will "catch" the recurse loop

I would expect the files to be named folder1_book1.xlsx, folder1_book2.xlsx, folder1_book3.xlsx.

But all of the attempted changes above give the same result. The first file is named folder1_folder1_book1.xlsx [INCORRECT], folder1_book2.xlsx[CORRECT], folder1_book3.xlsx[CORRECT].

A workaround might be writing an if statement for "not files that contain the sub-directory name" as suggested here. But the link searches for a text string not an object (probably not the correct term) like @_.Directory.Name. This post shows how to concatenate objects but not something like @_.Directory.Name. Having to put in an if statement seems like an unnecessary step if -Recurse worked the way it should, so I'm not sure this workaround gets at the heart of the issue.

I'm running windows 10 with bootcamp on a 2018 iMac (I'm in Windows a lot because I use ArcMap). Powershell 5.1.17134.858. Visual Studio Code 1.38.0. This is a task I would like to learn how to use more in the future, so explanations will help. I'm new to using PowerShell. Thanks in advance!

BonnieM
  • 191
  • 1
  • 13
  • 2
    Do you see the behavior if you instead collect the files up front and then iterate with `foreach`? – Bill_Stewart Sep 04 '19 at 22:03
  • 3
    as `Bill_Stewart` implied, that behavior is a side effect of how PoSh is loading the file list when you feed GCI directly into a pipeline. the fix is either [1] use a `foreach` **_loop_** instead of a `ForEach-Object` pipeline stage OR get the whole collection up front and then feed it to the pipeline. – Lee_Dailey Sep 04 '19 at 22:13
  • 2
    Possible duplicate of [Powershell, rename-item doesn't work as expected](https://stackoverflow.com/questions/42470793/powershell-rename-item-doesnt-work-as-expected) (pay attention to the note in the end of **mklements0**'s answer, thus: `(dir -Filter *.xlsx -Recurse) | Rename-Item...`) – iRon Sep 05 '19 at 07:41
  • @Lee_Dailey, what would a foreach loop look like in code? – BonnieM Sep 05 '19 at 19:49
  • @iRon thank you for clarifying what "up front" meant and pointing to the very end of that post. The () did the trick. I also found that instead adding `Sort-Object -Property Name |` as the second line works as well. Is this a solution or just a duplicate? – BonnieM Sep 05 '19 at 19:57
  • 1
    @BonnieM - you seem to have found one fix = wrapping the 1st stage of the pipeline in `()` to force it to fully evaluate before sending things to the next stage. ///// the `foreach` loop runs things in a LOOP instead of one-at-a-time thru the pipeline. so it would be something like `foreach ($Thing in $Collection) {Do-Stuff -To $Thing}` – Lee_Dailey Sep 05 '19 at 20:55
  • It works for me. Can you give a reproducible example that doesn't work (win10 ps 5.1)? – js2010 Oct 03 '19 at 17:42
  • Oh, I see it now without the -whatif. It's still reading the subdirectory after the rename. Parentheses around the first pipeline element makes sense. – js2010 Oct 03 '19 at 18:08

1 Answers1

0

This was a script I created for one of my customers that may help

<##################################################################################################################################

This script can be used to search through folders to rename files from their original name to "filename_foldername.extension". To use this script please configure the items listed below.

Items to Congfigure -$Original -$Source -$Destination -$Files

Also please change the Out-File date on line 29 to today's date ****Example: 2019-10-02****

We've also added a change log file that is named "FileChange.txt" and can be found in the location identified on line 30

>

$Original="C:\temp\test" #Location of ".cab" files copied
$Source="C:\temp\Test" #Location were ".cab" files are stored
$Destination="C:\temp\Test\2019-10-02" #Location were you want to copy ".cab" files after the file name change. Be sure to change the date to the date you run this script. The script creates a folder with todays date
$Files=@("*.cab") #Choose the file type you want to search for
$ErrorActionPreference = "SilentlyContinue" #Suppress Errors

Get-ChildItem $Original -Include "*.cab" -File -Recurse | Rename-Item -NewName {$_.BaseName+"_"+$_.Directory.Name +'.cab'}
New-Item -ItemType Directory -Path ".\$((Get-Date).ToString('yyyy-MM-dd'))"; Get-ChildItem -recurse ($Source) -include ($Files) | Copy-Item -Destination ($Destination) -EA SilentlyContinue
Get-ChildItem $Original | Where {$_.LastWriteTime -ge [datetime]::Now.AddMinutes(-10)} | Out-File C:\temp\test\2019-10-02\FileChange.txt