Remove extraneous characters from file name
I was tasked with taking a file repository a little overhead and removing the extra trash characters from the filename and saving the renamed file in a different directory folder.
File name example:
100-expresstoll.pdf 1000-2012-09-29.jpg 10000-2014-01-15_14.03.22.jpg 10001-2014-01-15_19.05.24.jpg 10002-2014-01-15_21.30.23.jpg 10003-2014-01-16_07.33.54.jpg 10004-2014-01-16_13.33.21.jpg 10005-Feb 4, 2014.jpeg 10006-O'Reilly_Media, _Inc..pdf
The first group of numbers at the beginning are record IDs and should be saved with the file extension. Anything else between the record IDs and the file extension needs to be dropped.
For example, the final name for the first three files would be:
100.pdf 1000.jpg 10000.jpg
I've read Deleting Characters and Editing Filenames in addition to other posts, but the complexity of the variable character length in front, the variable number of intermediate characters to be removed, and the variable file extension types really threw this outside of my limited PowerShell coverage.
source to share
Another approach without regex. Both of the following examples use the risk mitigation option -WhatIf
for debugging purposes.
Rename files:
Get-ChildItem -File | ForEach-Object {
$oldFile = $_.FullName
$newName = $_.BaseName.Split('-')[0] + $_.Extension
if ($_.Name -ne $newName) {
Rename-Item -Path $oldFile -NewName $newName -WhatIf
}
}
Rename and move files:
$newDest = 'D:\test' ### change to fit your circumstances
Get-ChildItem -File | ForEach-Object {
$oldFile = $_.FullName
$newName = $_.BaseName.Split('-')[0] + $_.Extension
$newFile = Join-Path -Path $newDest -ChildPath $newName
if ( -not ( Test-Path -Path $newFile ) ) {
Move-Item -Path $oldFile -Destination $newFile -WhatIf
}
}
source to share
You can use -replace
to perform this kind of string manipulation:
Get-ChildItem | foreach {
$old_name = $_.FullName
$new_name = $_.Name -replace '([0-9]+).*(\.[^.]*)$', '$1$2'
Rename-Item $old_name $new_name
}
Regular expression is the trick:
-
([0-9]+)
means match a series of digits (1 or more digits) -
.*
means meeting all -
(\.[^.]*)
means period match followed by any non-period characters -
$
means that the match must go to the end of the line
The first and third are special because they are surrounded by parentheses, which means you can use those values using dollar notation (for example $1
) in the replacement string.
source to share
Probably the most idiomatic way to solve this is as follows (assuming all files of interest - and others - are in the current directory):
Get-ChildItem -File | Rename-Item -NewName { ($_.BaseName -split '-')[0] + $_.Extension }
Add a general parameter -WhatIf
to the command Rename-Item
to view the rename operation.
Note that it Rename-Item
always renames items at their current location; to (also) move them, use Move-Item
.
If a target with the same name already exists, Rename-Item
reports a fatal error for each such case (without interrupting general processing).
Note that it can also happen if the input file name does not contain -
, as this will attempt to rename the file to itself.
Explanation:
-
Get-ChildItem -File
prints[System.IO.FileInfo]
objects representing files in the current directory that are piped (|
) toRename-Item
. -
Passing a script (
{ ... }
) block toRename-Item
-NewName
execute executable code for each input object, where it$_
represents the input object at hand.- Note that this almost undocumented but commonly used method is called the script -block [value] parameter, where the parameter that is for the pipeline input can be linked to the script block that indirectly handles the input.
-
($_.BaseName -split '-')[0]
-
Retrieves the 1st segment token from each basename of the input filename (filename without extension). -
+
since LHS is a string, it does string concatenation. -
$_.Extension
extracts the filename extension from each input file name.
source to share
I know this is not a PowerShell thing. If you just want something to work, this is the cmd batch file.
SETLOCAL ENABLEDELAYEDEXPANSION
SET "OLDDIR=C:\Users\lit\files"
SET "NEWDIR=C:\Users\lit\newdir"
FOR /F "usebackq tokens=*" %%a IN (`DIR /A:-D /B "%OLDDIR%\*"`) DO (
FOR /F "usebackq delims=- tokens=1" %%b IN (`ECHO %%a`) DO (SET "BN=%%b")
SET "EXT=%%~xa"
ECHO COPY /Y "%OLDDIR%\%%~a" "%NEWDIR%\!BN!!EXT!"
)
source to share