I'm creating a script that I can use to set up new user account in AD.
Early in the batch file I have a variable that is saved like this -
set state=%pspath% "St" -Value 'Gloucestershire'
pspath is populated later in the batch when the user is actually being created this part -
set pspath="Set-ItemProperty -Path 'CN=%firstname% %lastname%,%ou%' -Name"
powershell -nologo Import-Module ActiveDirectory;Set-Location AD:;%state%;
Firstname, lastname and ou is all populated without a problem, but in that second line when I'm using the %state% variable, %pspath% is ignore and the command comes out as
powershell -nologo Import-Module ActiveDirectory;Set-Location AD:;"St" -Value 'Gloucestershire'
instead of what it should be -
powershell -nologo Import-Module ActiveDirectory;Set-Location AD:;Set-ItemProperty -Path 'CN=%firstname% %lastname%,%ou%' -Name "St" -Value 'Gloucestershire'
How do I get all the variables to populate in the command properly instead of %pspath% being skipped?
Related
I have a folder with files of different naming patterns. For example:
S012344
S00abcd
DA01234
DAL1230
D13459A
MOV0001
M123004
Now I need to move all the files except the one which have the following naming patterns: (** means regular expression)
- S00****
- Starts with D and ends with A
- MOV****
I need to do this as part of a batch file, I searched a lot but didn't find any apt solutions to address this problem.
There are ambiguities in your question. But, here is a possible way to do it. If you are on a supported Windows system, then it will have PowerShell. When you are satisfied that the files will be moved correctly, remove the -WhatIf from the Move-Item command.
=== Move-FilesIWant.ps1
Get-ChildItem -File -Path 'C:\src\t\' |
Where-Object { $_.BaseName -notmatch '(^S00....$|^D.*A$|^MOV....$)' } |
ForEach-Object { Move-Item -Path $_.FullName -Destination 'C:\new\dir' -WhatIf }
If you must run it from a cmd.exe shell or .bat file script, use:
powershell -NoLogo -NoProfile -File '.\Move-FilesIWant.ps1'
I would like to create a PowerShell script that can import a CSV file (details.csv) with two headers (FileName and FileCreationTime). Ideally, the script would look for details.csv in the current location the script is saved.
It would create folders in the script's current location with the same name as FileName, and the creation date of said folder would then be changed to match FileCreationTime.
Example chunk of my CSV [made in A & B columns of Excel then saved as CSV (comma delimited)(*.csv)]:
FileName FileCreationTime
Alpha 5/17/2017
Bravo 12/23/2013
Charlie 11/8/2015
I have been searching for a solution, but nothing I do seems to be quite right. I currently have this:
Import-Csv -Path 'K:\Users\eschlitz\Thesis\details.csv' -Delimiter "," |
ForEach-Object {
$path = 'K:\Users\eschlitz\Thesis'
# Again, didn't want a definite path here, but I was trying different
# tweaks to see if I could get at least one instance to work correctly.
New-Item -Path $path -Name $$_.Filename -Type Directory
(Get-Item $_.Filename).CreationTime = (Get-Date $_.FileCreationTime)
}
My current error message:
Get-Item : Cannot find path 'K:\Users\eschlitz\Thesis\Alpha' because it does not exist.
I do not care about whether or not the hh:mm:ss part of the creation time is edited for the new folders, but it would be a bonus if I could standardize them all to 12:00:00 AM.
~~~~~~~~~~~~~~~~~~~~~~~Question Duplication Edit~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Suggested edit to show how my question is different from PowerShell: Change the timestamp (Date created) of a folder or file
Everything that I was able to find related to this did either only A)create folders from a CSV, or was B)script to edit the creation date of a single folder / or batch edit the creation date of multiple folders but only with a single new creation time. I wanted the script to hopefully fail if it would be unable to correctly find the new creation time unique to each new folder, thereby eliminating the need for me to manually delete wrong folders or edit the creation time manually.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Edit~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Just wanted to post the complete, working versions in case anyone needs them in the future.
#Adds folders to specified directory and modifies their creation date
Import-Csv -Path 'K:\Users\eschlitz\Thesis\details.csv' -Delimiter "," |
ForEach-Object {
$path = ' K:\Users\eschlitz\Thesis'
$dir = New-Item -Path $path -Name $_.Filename -Type Directory
$dir.CreationTime = [DateTime]::ParseExact($_.FileCreationTime,
'M\/d\/yyyy', [Globalization.CultureInfo]::InvariantCulture)
}
And a slightly different version depending on needs:
#Adds folders and then modifies their creation date where script+csv
#currently are
Set-Location -Path "$PSScriptRoot"
Import-Csv -Path ".\details.csv" -Delimiter ',' |
ForEach-Object {
New-Item -Path "$PSScriptRoot" -Name $_.FileName -Type Directory
(Get-Item $_.Filename).CreationTime =
([DateTime]::ParseExact($_.FileCreationTime, 'M\/d\/yyyy',
[Globalization.CultureInfo]::InvariantCulture))
}
The folder is not created b/c you have a typo in the New-Item statement ($$_.Filename → $_.Filename), and even if it were created Get-Item most likely wouldn't be able to find it, because it's looking in the current working directory, whereas you create the folder in $path. You can avoid the latter issue by capturing the DirectoryInfo object that New-Item returns in a variable:
$dir = New-Item -Path $path -Name $_.Filename -Type Directory
$dir.CreationTime = (Get-Date $_.FileCreationTime)
You may also need to actually parse the date string into a DateTime value (depending on your locale):
[DateTime]::ParseExact($_.FileCreationTime, 'M\/d\/yyyy', [Globalization.CultureInfo]::InvariantCulture)
If you defined the date in ISO format (yyyy-MM-dd) Get-Date should be able to digest it regardless of the system's locale.
This question already has answers here:
How to properly -filter multiple strings in a PowerShell copy script
(5 answers)
Closed 6 years ago.
I have this script and it's working 100% , but only for a single item
I want to loop the script and get content from a txt file
You see, my scipt search for a specific file and copy it to an existing folder with the same name of the file.
So what I want is to get the folder's name and the file's name from 2 txt files and loop the script
I have manage to get the content from the txt files but I can't loop the script if I add a second line with new values in my txt files.
I always get the error:
Get-ChildItem : Cannot convert 'System.Object[]' to the type
'System.String' required by parameter 'Filter'. Specified method is
not supporte d.
Ok this is my script:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned
# Setup source and destination paths
$Src = '\\192.168.0.216\home\'
$Dst = 'C:\TEST\120629B\'
# Wildcard for filter
$Extension = '120629B.jpg'
# Get file objects recursively
Get-ChildItem -Path $Src -Filter $Extension -Recurse |
# Skip directories, because XXXReadMe.txt is a valid directory name
Where-Object {!$_.PsIsContainer} |
# For each file
ForEach-Object {
# If file exist in destination folder, rename it with directory tag
if(Test-Path -Path (Join-Path -Path $Dst -ChildPath $_.Name))
{
# Get full path to the file without drive letter and replace `\` with '-'
# [regex]::Escape is needed because -replace uses regex, so we should escape '\'
$NameWithDirTag = (Split-Path -Path $_.FullName -NoQualifier) -replace [regex]::Escape('\'), '-'
# Join new file name with destination directory
$NewPath = Join-Path -Path $Dst -ChildPath $NameWithDirTag
}
# Don't modify new file path, if file doesn't exist in target dir
else
{
$NewPath = $Dst
}
# Copy file
Copy-Item -Path $_.FullName -Destination $NewPath
}
Ok this is what I have change and worked but is only working with one record
$Src = '\\192.168.0.216\home\'
$Dst = Get-Content 'C:\TEST\path.txt'
# Wildcard for filter
$Extension = Get-Content 'C:\TEST\file.txt'
The error message is telling you the problem, you can't use an array as the filter for get-childitem. you can probably nest a where-object filter inside of a foreach loop but the easiest way to accomplish what you are trying to do is going to be to loop through your extension filters and then run your loop inside of that loop. so wrap your entire Get-ChildItem loop in a Foreach loop as below.
Foreach($e in $extension){
*Your Code Here*
}
Of cource make sure to change the -Filter parameter of your Get-ChildItem from $Extension to $e
Like error says, -Filter expects a single string. Get-Content would be returning an object array for files with more than one line.
Since you are also using -Recurse consider using -Include instead of -Filter since it supports arrays of stings. This should without changing your input file or adding any other post processing. From [MSDN]
Specifies, as a string array, an item or items that this cmdlet includes in the operation. The value of this parameter qualifies the Path parameter. Enter a path element or pattern, such as *.txt. Wildcards are permitted.
Get-ChildItem -Path $Src -Include $Extension -Recurse
Note:
The Include parameter is effective only when the command includes the Recurse parameter or the path leads to the contents of a directory, such as C:\Windows*, where the wildcard character specifies the contents of the C:\Windows directory.
Same goes for -Exclude as well
I am new to Powershell and I am having an issue within a loop that I need assistance with. I am attempting to rename some files that are created as part of the process within the loop.
I have tested the code OUTSIDE of the loop and it works fine. However, when I try to put it in the loop, nothing seems to happen.
The files I need to rename are in the following locations…
(1)“\MYSERVER\MYCOMPANY\MYFOLDER\ MyPrintouts\EstimateImport\ImportPrintout.txt”
(2)“\MYSERVER\MYCOMPANY\MYFOLDER\ MyPrintouts\PostEntries\ImportPostEntries.txt”
I need to tack the date and time on the end. This code works for me OUTSIDE of the loop. I put it in a file I named RenameFiles.ps1
#File location
$ImportPrintout = “\\MYSERVER\MYCOMPANY\MYFOLDER\MyPrintouts\EstimateImport\ImportPrintout.txt”
$ImportPostEntries = “\MYSERVER\MYCOMPANY\MYFOLDER\ MyPrintouts\PostEntries\ImportPostEntries.txt”
#Find and rename the import printouts
Get-ChildItem $ImportPrintout -Filter "ImportPrintout.txt" | ForEach-Object {
Rename-Item $_.FullName "$BackupFolder$($_.BaseName -replace " ", "_" -replace '\..*?$')$(Get-Date -Format "MMddyyyy-HHmmss").txt"}
Get-ChildItem $ImportPostEntries -Filter "ImportPostEntires.txt" | ForEach-Object {
Rename-Item $_.FullName "$BackupFolder$($_.BaseName -replace " ", "_" -replace '\..*?$')$(Get-Date -Format "MMddyyyy-HHmmss").txt"}
This is how I added it to the loop as I want the files renamed BEFORE the next file is processed…
#Define actions after an Event is Detected
$action = {$files = Get-ChildItem -Path $watcher.Path -Filter $watcher.Filter #-Recurse
foreach ($file in $files)
{
#Define variables for log file
$changeType = $Event.SourceEventArgs.ChangeType #Your event trigger "Created"
$fileDate = $file.LastWriteTime #Date/Time Estimate was created
#logline contains = Date/Time of import, Created, Date/Time Created, filename
$logline = "$(Get-Date), $changeType, $fileDate, $file"
#Actions to take ==============================================================
#Write details to the log
Add-Content "“\\MYSERVER\MYCOMPANY\MYFOLDER\EstimateImportLog.txt" -value $logline
#Copy the estimate to the "ToBeProcessed" folder
Copy-Item $file.FullName -Destination $copyTo
#Move the estimate to the "EstimateHistory" folder
Move-Item $file.FullName -Destination $moveTo -Force
#Run the powershell script that launches the .bat file that launches the macro
Invoke-Expression "& '\\MYSERVER\MYCOMPANY\MYFOLDER\PSscriptToRunBATfile.ps1'"
#Pause the script for 30 seconds to allow the estimate to finish posting
Start-Sleep -Seconds 30
Invoke-Expression "& '“\\MYSERVER\MYCOMPANY\MYFOLDER\RenameFiles.ps1'"
}
}
This seems to “break” my loop. However, I need this to be done BEFORE going to the next file. How can I accomplish renaming these files before moving on. Any assistance would be greatly appreciated. Thank you!
As far as the loop failing, you're probably encountering an error. Either set your $ErrorActionPreference to Continue or set it to Stop and wrap try/catch blocks around your copy-item and move-item to detect and handle errors.
That probably also addresses the failure of the copy-item/move-item to change the file name, it's running into an error trying to perform that action and failing.
I have a folder with oracle bi publisher reports
Folder/Usage Trend Report.xdmz
Folder/Usage Summary Report.xdmz
Folder/Charge Trend Report.xdmz
Folder/Consolidation Reports.xdmz
Folder/Charge Summary Report.xdmz
Each report is like zip file and contains some files
_datamodel.xdm
~metadata.meta
security.xml
I want to make a batch file, searches all the _datamodel.xdm file in order to find a literal (eg INVOICE_NBR or invoice_nbr)
The output will be something like
Report Name Literal Usages
Consolidation Reports.xdmz INVOICE_NBR 1
Is there anyone to help me do it ?
Thanks
In the future, please show what you've tried to solve the problem on your own, and where you're getting stuck. For this time, I found the challenge interesting, so I whipped up a beginning for you. It's a Batch + PowerShell hybrid script. Save it with a .bat extension and salt to taste. Be advised that the regexp object that performs a count of strings uses case-sensitive matching; so "INVOICE_NBR" would not increment the count when searching for "invoice_nbr".
<# : batch portion
#echo off & setlocal
set "outerfile=*.xdmz"
set "innerfile=_datamodel.xdm"
set "search=invoice_nbr"
rem // re-launch self with PowerShell interpreter
powershell "iex (${%~f0} | out-string)"
goto :EOF
: end batch / begin PowerShell hybrid chimera #>
add-type -as System.IO.Compression.FileSystem
# // encapsulate loop into a collection for select | format-table
&{ foreach ($archive in (gci $env:outerfile)) {
# // create a temporary directory within %temp%
$tempdir = New-Item -path $env:temp -name ([Guid]::NewGuid()) -type dir
[IO.Compression.ZipFile]::ExtractToDirectory($archive, $tempdir)
# // For each innerfile found within the zip archive...
gci -path $tempdir -filter $env:innerfile -recurse | %{
new-object PSObject -property #{
"Report Name" = $archive.Name
"Usages" = ([regex]::Matches((gc $_.FullName | out-string), $env:search)).count
"Literal" = $env:search
}
}
Remove-Item $tempdir -recurse -force
} } | select "Report Name",Literal,Usages | format-table -auto
Example output:
Report Name Literal Usages
----------- ------- ------
Usage Summary Report.xdmz invoice_nbr 2
Usage Trend Report.xdmz invoice_nbr 2
If you want case-insensitive matching, add the following as a third argument to the [regex]::Matches() function:
[Text.RegularExpressions.RegexOptions]::IgnoreCase