Powershell - how to extract substring - powershell

I am new in learning powershell. Trying to extract "Testfile.txt" from the Azure Data lake Store path \data\sb\published\Juned\Testfile.txt in my Powershell Script. I am using ("\data\sb\published\Juned\Testfile.txt" -split '\')[0].
This is showing the error
parsing "\" - Illegal \ at end of pattern.
At line:1 char:1
+ ("\data\sb\published\Juned\Testfile.txt" -split '\')[0]
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException

You can use the split-path cmdlet with the -leaf parameter to get the filename with extenstion :
split-path "\data\sb\published\Juned\Testfile.txt" -leaf
If you absolutly want to stick with your split approach you need to select the last element ([-1] instead of [0] which is the first element) : "\data\sb\published\Juned\Testfile.txt".split('\')[-1]

These 2 methods worked for me:
split-path "H:\Documents\devops\tp-mkt-SPD-38.4.10.msi" -leaf
tp-mkt-SPD-38.4.10.msi
[System.IO.Path]::GetFileName("C:\abc\xyz\test.txt")
test.txt
[System.IO.Path]::GetFileNameWithoutExtension("C:\abc\xyz\test.txt")
test

Related

PowerShell script to set "date created" to specific times according to a csv file

I have some thousands of files in a folder that I need to bulk edit their creation time to a specific order.
I have prepared a csv file with all file names and the preferred creation times, like this:
filename;filecreationTime;
file1.mp4;10/11/2022 2:50;
file2.mp4;10/11/2022 2:49;
file3.mp4;10/11/2022 2:49;
etc
I have used this suggestion to a similar previous question: https://stackoverflow.com/a/36348448/20467894 and created a code like this:
Set-Location 'path to files'
Import-Csv -Path 'path to csv file' |
ForEach-Object { (Get-Item $_.filename).CreationTime = (Get-date $_.filecreationTime) }
The outcome is this error, for each line of the csv:
Get-Item : Cannot bind argument to parameter 'Path' because it is null.
At line:2 char:32
+ ForEach-Object { (Get-Item $_.filename).CreationTime = (Get-date ...
+ ~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-Item], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.GetItemComm
and
What am I doing wrong?
EDIT: After Theos' comment, it run once in a sample subset of my files but never run again. Now it can indeed read the filenames, but it brings a new error:
Get-date$_.filecreationTime : The term 'Get-date$_.filecreationTime' is not recognized as the name of a cmdlet, functio
n, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is
correct and try again.
At line:2 char:57
+ ... (Get-Item $_.filename).CreationTime = (Get-date$_.filecreationTime) }
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Get-date$_.filecreationTime:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Thanks everyone for your suggestions.
As pointed out by Theo, the problem was that in my language and regional formats the delimiter of the csv files is set to ";" instead of ",", as the latter is used as decimal...
So I had to insert an additional argument into the import csv (that was not obvious by the error expression), in order to clarify the non default delimiter:
-Delimiter ';'
So, the correct code for me was the following:
Set-Location 'path to files'
Import-Csv -Delimiter ';' -Path 'path to csv file' |
ForEach-Object { (Get-Item $_.filename).CreationTime = (Get-date $_.filecreationTime) }

Powershell Copy-item fails on unc path with space and ampersand

I am trying to use the powershell Copy-Item command to copy a file to a UNC Path.
Unfortunately, the UNC path on this production server has both spaces and an ampersand in the name.
I've tried a bunch of things, but haven't had any luck yet.
Could you please suggest a way to resolve this issue.
$InvokeExpressionPath = "\\servername\This Folder Has Spaces & Ampersand\Folder"
$TransfersSharePath = Invoke-Expression $InvokeExpressionPath
$TransfersSharePathFile = $InvokeExpressionPath + "\" + $FileName
Copy-Item -Path $CheckFileExists -Destination $TransfersSharePathFile -Force -ErrorAction SilentlyContinue
This is the error message that I get:
Invoke-Expression : At line:1 char:41
+ \\servername\This Folder Has Spaces & Ampersand\Folder
+ ~
The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an ampersand in double quotation marks ("&") to pass it as part of a string.
At E:\Scripts\CopyFile_Test.ps1:33 char:27
+ $TransfersSharePath = Invoke-Expression $InvokeExpressionPath
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ParserError: (:) [Invoke-Expression], ParseException
+ FullyQualifiedErrorId : AmpersandNotAllowed,Microsoft.PowerShell.Commands.InvokeExpressionCommand
If I try to wrap the ampersand in double-double quotes (""&""), I get this error when the code runs.
\\servername\This : The term '\\servername\This' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was
included, verify that the path is correct and try again.
At line:1 char:1
+ \\servername\This Folder Has Spaces "&" Ampersand\Folder
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (\\servername\This:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
DEBUG: This is the value of TransfersSharePathFile - \\servername\This Folder Has Spaces & Ampersand\Folder\file.zip
Copy-Item : Illegal characters in path.
At E:\Scripts\CopyFile_Test.ps1:36 char:5
+ Copy-Item -Path $CheckFileExists -Destination $TransfersSharePathFile -Force ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Copy-Item], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.CopyItemCommand
Thanks in advance for your help.
Thanks very much to AdamL and dread1 for their help. I used both suggestions.
For reference, this is what the working code now looks like.
$InvokeExpressionPath = "\\servername\This Folder Has Spaces & Ampersand\Folder"
$TransfersSharePathFile = Join-Path -Path $InvokeExpressionPath -ChildPath $FileName
$TransfersSharePathFile = $InvokeExpressionPath + "\" + $FileName
Copy-Item -Path $CheckFileExists -Destination $TransfersSharePathFile -Force -ErrorAction SilentlyContinue
Ampersand or spaces in path are not the problem. You're trying to use Invoke-Expression supplying path as parameter, which is not a valid command. Get rid of $TransfersSharePath line and use what's in $InvokeExpressionPath directly. Just change double quotation marks to single just in case. Also I suggest you create path using Join-Path instead of contatenating the strings.
Try:
$InvokeExpressionPath = '\\servername\This Folder Has Spaces & Ampersand\Folder'
Should do the job

Method invocation failed ... does not contain a method named 'op_Addition'

I have a bit of a headscratcher where I have a powershell script references another. At the top of this script I have the reference,
. $PSScriptRoot\bin\functions.ps1
This throws the error,
Method invocation failed because [System.IO.DirectoryInfo] does not contain a method named 'op_Addition'.
At ....\bin\functions.ps1:5 char:1
+ $LogPath = $ParentDirectory + '\InstallLog_' + $CurrentDate + '.txt'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (op_Addition:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
I cannot figure out why this is happening. Here is the code in the first 5 lines of the second file. The issue is with $Logs assignment.
$invocation = (Get-Variable MyInvocation).Value
$CurrentDate = Get-Date -format "yyyy_MM_dd_hhmmss"
$CurrentDirectory = Split-Path $invocation.MyCommand.Path
$ParentDirectory = (get-item $CurrentDirectory).parent
$LogPath = $ParentDirectory + '\InstallLog_' + $CurrentDate + '.txt'
If I hardcode the path in the $Logs variables, its fine.
If I use the variable, $CurrentDirectory instead of $ParentDirectory, its fine.
If fails with $ParentDirectory or use the statement in line for $Logs. I don't think what I'm doing is complicated nor anything that someone else has not done. Is there some nuance I do not know about?
Thanks,
I discovered right after I posted that when you use get-item you do not get a string back, you get an object.
The error is being thrown because I was trying to concatenate an object with another string. I needed to use the following,
$ParentDirectory = (get-item $PSScriptRoot).parent
$LogPath = $ParentDirectory.FullName + '\logs\InstallLog_' + $CurrentDate + '.txt'

Passing arguments to $webclient.DownloadFile() in PowerShell

I am using PowerShell for the first time for a small task. I have a text file on disk with file download url links.Text file has several links line by line. I want to download to disk. I tried using the following code.
$filepath = "C:\Users\User\Desktop\filelinks.txt"
$files = Get-Content $filepath
$i=0
foreach($fileurl in $files){
$webclient = New-Object System.Net.WebClient
$file = "C:\Users\User\Desktop\"+$i+".csv"
$webclient.DownloadFile($fileurl,$file)
$i++
}
But I get the following error
Exception calling "DownloadFile" with "2" argument(s): "Illegal characters in path."
At line:8 char:1
+ $webclient.DownloadFile($fileurl,$file)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ArgumentException
The links in text file
"http://www.football-data.co.uk/mmz4281/1617/I1.csv"
"http://www.football-data.co.uk/mmz4281/1617/E1.csv"
"http://www.football-data.co.uk/mmz4281/1617/E2.csv"
"http://www.football-data.co.uk/mmz4281/1617/SP1.csv"
"http://www.football-data.co.uk/mmz4281/1617/D1.csv"
How should i pass the right arguments here
It looks like the URLs in your file are enclosed in "..." - actual double quotes that, when read with Get-Content, become a literal part of the lines read - which is not the intent (embedded " chars. are not allowed in URLs, which explains the error you saw).
Either: Update file C:\Users\User\Desktop\filelinks.txt by removing the enclosing " instances from each line.
Or: Remove the enclosing " instances after having read the lines with Get-Content:
$fileurl = $fileurl -replace '^"(.*)"$', '$1'

Trying to use built-in PS1 methods Get-Date, Convert-Path, rename-item getting errors

I am new to PowerShell and trying to write my first script to copy files from one directory to another and then rename the files in the $DESTINATION directory once they are copied over there.
I am executing the script below from C:\Scripts directory on my machine.
The first foreach loop works great and my files land in the $DESTINATION.
But when I to through the 2nd loop I get the errors below
Any help/direction would be appreciated. Thanks.
Here is my code:
# Define variables.
$Source = "C:\ETLFILES\WinSCP\FilesETL\*.*"
$Destination = "C:\ETLFILES\WinSCP\SFE_Archive\"
$DestinationFiles = "C:\ETLFILES\WinSCP\SFE_Archive\*.*"
# Create the $sourceFileList variable to loop through
$sourceFileList = Get-ChildItem -path $Source
# Loop through the $soureFileList and copy the items to the $Destination.
foreach ($item in $sourceFileList) {
Copy-Item -Path $Source -Destination $Destination
}
# Create the $destinationFileList variable to loop through
$destinationFileList = Get-ChildItem -path $DestinationFiles
# Loop through the $destinationFileList and rename the files with appended DateTime stamp.
foreach ($itemDest in $destinationFileList) {
$Date = (Get-Date).ToString("yyyyMMdd_HHmmss")
$newFileName = $Date + "_" + $itemDest
Rename-Item $itemDest $newFileName
}
Here are the errors I'm getting and I think that I need to change the -path as it is looking to where the script is executing from and not looking at the $DestinationFiles directory like it looked to the $Source above:
PS C:\Scripts> C:\Scripts\ArchiveSFE_files.ps1
Rename-Item : Cannot rename the specified target, because it represents a path or device name.
At C:\Scripts\ArchiveSFE_files.ps1:21 char:5
+ Rename-Item $itemDest $newFileName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.RenameItemCommand
Rename-Item : Cannot rename the specified target, because it represents a path or device name.
At C:\Scripts\ArchiveSFE_files.ps1:21 char:5
+ Rename-Item $itemDest $newFileName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.RenameItemCommand
Rename-Item : Cannot rename the specified target, because it represents a path or device name.
At C:\Scripts\ArchiveSFE_files.ps1:21 char:5
+ Rename-Item $itemDest $newFileName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.RenameItemCommand
Rename-Item : Cannot rename the specified target, because it represents a path or device name.
At C:\Scripts\ArchiveSFE_files.ps1:21 char:5
+ Rename-Item $itemDest $newFileName
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Rename-Item], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.RenameItemCommand
PS C:\Scripts>
PowerShell can be a bit tricky if you're used to text-based languages and tools, because everything in PowerShell is a .NET object.
This line:
$newFileName = Get-Date + "_" + $item # .ToString("yyyyMMdd-HHmmss") + "_" + $item
will most certainly result in an error. Get-Date returns a [datetime] object.
Although [datetime] does support the + operator, it expects an argument of the type [timespan] - and the string "_" can't be converted to a timespan.
What you want is a string representing the current date. Either use the ToString() statement that you've commented out, or use the -Format parameter to produce a formatted string instead of a [datetime] object:
$newFileName = (Get-Date).ToString("yyyyMMdd-HHmmss") + "_" + $item
or
$newFileName = (Get-Date -Format "yyyyMMdd-HHmmss") + "_" + $item
I'm not a betting man, but I'll bet the error you're having is this one.
Get-Date : Cannot bind parameter 'Date'. Cannot convert value "+" to type "System.DateTime".
Error: "String was not recognized as a valid DateTime."
This is because the code you've got here is trying to add a character to a PowerShell DateTime object, and that simply does not fly. You can pick a single property though and concatenate characters onto that, however.
But, I noticed that you commented out some lines in your code, and am guessing that you'd like to get the date in this format: "yyyyMMdd-HHmmss".
If that's so, this little snippet will do that for you:
# Define logic to rename and copy .
foreach ($item in $sourceFileList) {
$newFileName = $(Get-Date -UFormat %Y%m%d-%H%m%S) + "_" + $item
"the item $($item.BaseName) would become $newFileName"
}
This will output to the screen the new name for the file, like this:
the item q1 would become 20160921-110907_q1.png
the item q2 would become 20160921-110907_q2.png
the item q3 would become 20160921-110907_q3.png
You can comment out that line once you're happy with the new name. And the best part? Just drop this into your code inplace of your current $newFileName line and it will work with your previous code.
If I'm wrong, let me know the error you're getting and I'll help you get this sorted.
Looks like you are trying to write a file with : in the time part of the Get-Date when you try to rename to $newFileName. This will kick an error out.
$Date = Get-Date.ToString("yyyyMMdd_HHmmss")
$newFileName = $Date + "_" + $item
Include the above and that should prevent that problem.
thanks for everyone's help and input. I really appreciate it. I was finally able to resolve my problem whereby in the variable assigned in the foreach loop the FULL PATH was being defined that is what was generating the errors above. Once I used the .NAME property the issue was resolved. Thanks again to everyone.