1

I am trying to batch rename files in a folder. For example, right now I want to remove the character at the second index in the names of all of the files in a given folder. I have written a Java program that will do this given the path of the file.

The problem is that I am trying to batch the process with PowerShell, and I have very little knowledge of PowerShell. I basically just started using it today, and mainly to test run my Java program from the command line. I decided to try PowerShell for this because I saw a YouTube video where someone used PowerShell recursively to remove a certain character (like a "-") from every spot it appears in every file name in a folder. I thought maybe I could recurse with PowerShell to batch the process of changing every file name.

I want to recursively call the Java program with PowerShell and have PowerShell pass in each path of each file one by one in a folder to the Java program. I don't know if this is possible, but I'm hoping it is.

I have tried the following, though since I don't really any knowledge of PowerShell, I don't really know what to try. "Copy" is the name of the folder in which the files I want to modify are located.

get-childitem -recurse | java -cp "C:\Users\Media PC\Documents\Renamer\src\main\java" org.example.Main $_.name

I am getting the Java program to run, because I'm getting an error back from the program saying I didn't pass in a proper file path.

mklement0
  • 382,024
  • 64
  • 607
  • 775
Ryland301
  • 21
  • 1
  • 1
    You would need to place your call inside a `Foreach-Object` (`%` is the alias) loop to process them as they come down the pipeline: `.... | % { java .... $_.FullName }`. You would want to pass the `FullName` property as it's the entire path and while doing a *recursive* pull. This is because, the directory you're currently on is where it would attempt to resolve the path to. – Abraham Zinala Jan 18 '23 at 22:17
  • 1
    Of course, you could do the recursion in the app. The nio classes and the visitor classes make this easy – g00se Jan 18 '23 at 22:25

1 Answers1

1

Building on Abraham Zinala's helpful comment:

Leaving aside the fact that invoking an external program (i.e., creation of a child process) file by file is inefficient:

Get-ChildItem -File -Recurse | ForEach-Object {
  java -cp "C:\Users\Media PC\Documents\Renamer\src\main\java" org.example.Main $_.FullName
}

Note: The -File switch limits results to just files (doesn't include directories).

  • PowerShell's automatic $_ variable can only be used inside script blocks ({ ... }), so using $_.name as an argument as-is won't work.

    • See this answer for all contexts in which $_ is meaningfully defined.
  • In order to pass an argument to a command that isn't designed to take its input directly from the pipeline, use the ForEach-Object cmdlet for custom-processing of each input object one at a time.

    • Inside the script block passed to it, you can use $_ to refer to the pipeline input object at hand.

    • Get-ChildItem outputs instances of the following .NET types:

      • System.IO.DirectoryInfo(for directories) and

      • System.IO.FileInfo (for files)

      • Their .FullName property contains their full, file-system-native path, so $_.FullName is a robust way to refer to just that. Given that .Name only reports the mere file name, it wouldn't be sufficient to identify the file at hand in a recursive traversal of the current dir.

        • In PowerShell (Core) 7+, you could use just $_, because there such instances consistently stringify as the value of their .FullName property (when passing arguments to an external program, objects are implicitly stringified) - unfortunately, this is not the case in Windows PowerShell; see this answer.
mklement0
  • 382,024
  • 64
  • 607
  • 775