Trying to create a folder with variables from Read-Host - powershell

I've built a tiny little script to create folders from information that is in a .csv but the folder naming convention could be different every time.
So I was wondering if there was a way I could have the variables pre-saved and just call them when I come to create the folders, i.e I could have 732881-English or English732881 depending on what I write in the read-host, the only problem is it wont print in the file name i've tried using ${variable) ${variable} and nothing appears to work
I've attatched a similiar code here to what I am using
Import-Csv "\\Desktop\Powershell Testing\staffdata.csv"
$students = Import-Csv "\\Desktop\Powershell Testing\staffdata.csv"
foreach($object in $students) {
$id = $object.'Roll Number'
$subject = $object.'Subject'
$foldername = Read-Host "Enter Folder Name"
New-Item -Path "\\Desktop\Powershell Testing\ExamHomes\$foldername" -ItemType Directory
}

Related

How to create a powershell script to move specific files to a different location?

So I have been tasked to write a script that will move files from one folder to another folder, which is easy enough. The problem I am having is the files are for accounts so there will be a file called DEA05292020.pdf and another file called TENSJ05292020 and each file needs to go to a specific folder (EX. the DEA05292020.pdf file needs to be moved to a folder called DEA and the TENSJ05292020 will move to the TENSJ folder. There are over a hundred different accounts that have their own specific folder. The files all start off in our Recon folder and need to be moved at the end of each month to their respective accounts folder. So my question is how could I go about creating a powershell script to make that happen. I am very new to powershell and have been studying the "Learn Powershell in a Month of Lunches" and have a basic grasp of it. So what I have so far is very simple where I can copy the file over to the new folder:
copy-item -path "\Sageshare\share\Reconciliation\PDF Recon Center\DEA RECON 05292020" -destination "Sageshare\share\Account Rec. Sheets\Seperate Accounts\DEA"
This works but I need a lot more automation in regards to seperating all the different account names in the PDF Recon Center folder. How do I make a script that can filter the account name (IE: DEA) and also the month and year from the name of the file (IE: 052020 pulled out of the 05292020 part of the filename)?
Thanks!
If #Lee_Dailey wants to write the code and post it here, I'll delete my answer. He solved the problem, I just code monkeyed it.
Please don't test on everything at once, run it in batches so you can monitor its behavior and not mess up your environment. It moves files in ways you may not want, i.e. if there is a folder named a it'll move everything that matches that folder into it. If you want to prevent this you can write the prescanning if there is a folder more "closely matching" that name before it actually creates the folder itself. Pretty sure it does everything you want however in the simplest way to understand. :)
$names = $(gci -af).name |
ForEach-Object {
if (-not ($_.Contains(".git"))){
$_
}
}
if ( $null -eq $names ) {
Write-Host "No files to move!"
Start-Sleep 5
Exit
}
$removedNames = $names |
ForEach-Object {
$_ = $_.substring(0, $_.IndexOf('.')) # Remove extension
$_ -replace '[^a-zA-Z-]','' # Regex removes numbers
}
$removedNames = $removedNames |
Get-Unique # Get unique folder names
$names |
ForEach-Object {
$name = $_
$removedNames |
ForEach-Object {
if ($name.Contains($_)) # If it matches a name
{
if (-not (Test-Path ".\$_")) { # If it doesn't see the folder
New-Item -Path ".\" `
-Name "$_" `
-ItemType "directory"
}
Move-Item -Path ".\$name" `
-Destination ".\$_" # Move file to folder
}
}
}

How do I copy multiple files from multiple hosts in powershell?

I am trying to make a powershell script (5.1) that will copy several files and folders from several hosts, these hosts change frequently therefore it would be ideal if I can use a list that I can append when required.
I have this all working using xcopy so I know the locations exist. I want to ensure that if a change is made when I am not In work someone can just add or remove a host in the text file and the back up will continue to work.
The code I have is supposed to go through each host in my list of hosts and copy all the files from the list of file paths before moving onto the next host.
But there are 2 errors showing up:
The term '\REMOTEHOST\c$\Users\Public\desktop\back-up\$Computers' 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:8 char:17
and:
copy-item : Cannot find path '\HOST\C$\LK\Appdata\Cmmcfg C$\LKAppData\Errc C$\LK\Appdata\TCOMP C$\LK\Probes C$\LK\Appdata\CAMIO C$\LK\Appdata\LaunchPad C$\LK\Appdata\Wincmes
C$\barlen.dta C$\Caliprogs C$\Cali' because it does not exist.
This does not seem to reading through the list as I intended, I have also noticed that the HOST it is reading from is 6th in the list and not first.
REM*This file contains the list of hosts you want to copy files from*
$computers = Get-Content 'Y:\***FILEPATH***\HOSTFILE.txt'
REM*This is the file/folder(s) you want to copy from the hosts in the $computer variable*
$source = Get-Content 'Y:\***FILEPATH***\FilePaths.txt'
REM*The destination location you want the file/folder(s) to be copied to*
$destination = \\**REMOTEHOST**\c$\Users\Public\desktop\back-up\$Computers
foreach ($item in $computers) {
}
foreach ($item in $source) {
}
copy-item \\$computer\$source -Destination $destination -Verbose
Your destination variable needs to be enclosed in quotes. To have it evaluate other variables inside of it, enclose it in double quotes. Otherwise PowerShell thinks it's a command you are trying to run.
$destination = "\\**REMOTEHOST**\c$\Users\Public\desktop\back-up\$Computers"
cracked it, thank you for your help. I was messing up the foreach command!I had both variables set to Item, so I was confusing things!
foreach ($itemhost in $computers) {
$destination = "\Remotehost\c$\Users\xoliver.jeffries\desktop\back-up\$itemhost"
foreach ($item in $source)
{copy-item "\$itemhost\$item*" -Destination $destination -Verbose -recurse}
}
Its not the neatest output but that's just a snag! the code now enables me to use a list of hosts and a list files and copy them to a remote server!

Using powershell to move/make folders/subfolders based on filename

I don't really have much experience in powershell but I have files that I need to organize. The files are all pdf and will have a format similar to "Dept123_Name_year.pdf".
I want to move the documents into a folder based on "Dept123" and a sub folder "Name". If the folder is yet to exist I would like it to create the folder/subfolder.
To make it easier I was thinking of using creating an "Organize" folder on the desktop and running the program on that. If you think it'd be easier some other way, let me know.
Thanks in advance.
You can use a regular expression to match the different components of the filenames, then generate a directory structure based on that. The -Force parameter of mkdir lets you ignore whether or not the directory already exists:
$list = ls
for ($i=0; $i -le $list.Length; $i++) {
if ($list[$i].Name -match '([A-Za-z0-9]+)_([A-Za-z]+)_.*\.pdf') {
$path = Join-Path $matches[1] $matches[2]
mkdir -Force -Path $path
cp $list[$i] "$path\."
}
}
The regular expression part is in the quotes; you might need to modify it to suit your specific needs. Note that the sections in round brackets correspond to the different parts of the name being extracted; these parts are loaded, in order, into the $matches variable, which is generated automatically. E.g. '([A-Za-z0-9]+)\.txt' will match any text file with only letters or numbers in the name, and will stick the actual name - minus the extension - into $matches[1].
Using regex and full-form Powershell:
# using ?<name> within a () block in regex causes powershell to 'name' the property
# with the given name within the automatic variable, $matches, object.
$Pattern = "(?<Dept>.*)_(?<Name>.*)_(?<Year>.*)\.pdf"
# Get a list of all items in the current location. The location should be set using
# set-location, or specified to the command by adding -Path $location
$list = Get-ChildItem
# Foreach-Object loop based on the list of files
foreach ($file in $list) {
# send $true/$false results from -matches operation to $null
$File.Name -matches $Pattern 2> $Null
# build destination path from the results of the regex match operation above
$Destination = Join-Path $matches.Dept $matches.Name
# Create the destination if it does not exist
if (!(Test-Path $Destination) ) {
New-Item -ItemType Directory -Path $destination
}
# Copy the file, keeping only the year part of the name
Copy-Item $file "$destination\$($matches.year)"+".pdf"
}

Powershell - Specifying variable path for usernames

I have tried searching for this, but I do not think I am using the correct words.
I am creating a script that needs to work on many environments. One of the specifications, is that I need to be able to delete a certain directory in a users AppData. Problem with it, is I do not know how to set a dynamic path.
I.e. C:\Users\User1\AppData\Local\X compared to C:\Users\User2\AppData\Local\X
How would I get and specify a series of user accounts on the local machine, ideally with out polling AD?
Check out the environment variables for paths to local resources using Get-ChildItem like so:
Get-ChildItem -Path env:
This will show you all environment variables and their value without the need to query Active Directory, the one you want for AppData\Local is called LOCALAPPDATA
To use an environmental variable in a function the syntax is $ENV:<Name> so to use the environmental variable for LOCALAPPDATA you would use $ENV:LOCALAPPDATA
Play around with the environmental variables and start coding your script, if you have additional questions you can then post your script and we can contribute a more specific answer to help you out :)
To get user names from AD, AD module must be installed on the system from which you run the queries.
#Export to a csv file user names and use it as the source.
Note that this command will export all users from your AD.
Get-ADuser -filter * | select name | Export-Csv c:\users.csv
$users = Import-Csv c:\users.csv
Foreach ($user in $users.name) {
$path = "c:\users\$user\appdata\local\X"
if ( $(Try { Test-Path $path.trim()} Catch { $false }) ) {
Remove-Item $path -Force -Recurse
}
Else {
write-host "Path not found"
}
}

Read text file and run a copy command for each line in the text file

I am trying to write a Powershell script that will read a text file on my desktop that is filled with user names, then go out to a specified folder on our network share, lets say u:\data and copy the contents from that folder to another network share lets says y:\information, for each user in the text file.
How would this be written?
I have tried several things with reading the text file then trying several commands to copy and paste but they each failed.
UPDATE:
Below is what I have done so far:
$user = Get-Content "test.txt"
$path = "\\abnas2\abusers\users"
$path2 = "\\abnas2\abdept\dept\testcopy"
$Copy = Copy-Item -path $path\$user\ * -Destination $path2\$user
I had one username in the test.txt file called user1 and it pulled the name, and copied perfectly.
Now if I add more than one name to the test.txt file and run the above, it errors out. The error it returned made it look like the 3 user names in the list were one user name.
What I need this to do is run the command for each name on the list. I was thinking I could use the foreach command But not sure how to do it.
UPDATE - 04\09\2014:
I have tried the following and am getting an error back:
$user = Get-Content "test.txt"
$path = "\abnas2\abusers\users"
$path2 = "\abnas2\abdept\dept\testcopy"
$Copy = Copy-Item -path $path\$user* -Destination $path2\$user
foreach($username in $user) {
Copy-Item -path $path\$username* -Destination $path2\$username\
}
When I run it I am getting the following error:
Copy-Item : An object at the specified path \\abnas2\abusers\users\user1 user2 user3 does not exist.
These are the names in my test.txt file, is there a way to get it to read one line at a time and execute the copy and when done go to the next name on the list and do the same? I'm not sure how to get it to do that.
You can use foreach
In this case:
foreach($username in $user) {
Copy-Item -path $path\$username\* -Destination $path2\$username\
}
would copy the contents of each named folder in $user under $path to its corresponding folder in $path2.