Code below works when I am in a directory:
gci | % {rni $_.Name ($_.Name -replace '120', '121')}
How do I create a batch file with powershell code that will work in every directory without errors. I just want to start file.bat that will rename all files in every folder where file.bat is located?
powershell -C "gci | % {rni $_.Name ($_.Name -replace '120', '121')}"
That doesn't work, here is error:
Expressions are only permitted as the first element of a pipeline.
At line:1 char:52 + gci | {rni $_.Name ($_.Name -replace '501', '121')} <<<<
Comedy answer:
echo Hi
is a batch file that will "work in any directory without errors", which is literally what you asked for.
Half serious answer, here is a batch file which will do the equivalent renaming of 120 to 121 in files in the current folder, what your PowerShell does, which is plausibly what you ask for:
#echo off
setlocal ENABLEDELAYEDEXPANSION
for %%f in (*120*) do (
set _f=%%f
ren "%%f" "!_f:120=121!"
)
Although even though you asked about Batch files and tagged the question about batch files, I suspect that's not what you want. Maybe you mean "how can I specify the directory for it to run against?" Then maybe this:
powershell -C "gci '%1' | % {rni $_.Name ($_.Name -replace '120', '121')}"
Where you save this as a batch file to run from a command prompt, %1 is the parameter you give to the batch file which is embedded in the PowerShell code, quoted as the input to gci. Then you could run myscript.bat "c:\data files" which would launch PowerShell and rename files in "c:\data files\".
Or maybe if you are asking more about the "with no errors" part from your title, then you need to accept that you might not have permission to list folder contents, or permission to rename files, or renaming files might lead to clashing names, in that case what you need is to add
`-ErrorAction -Ignore`
to gci and to rni, which will make them "run without errors", in a sense.
Serious answer: % is a special character in batch files, you need to escape it by writing it twice.
powershell -C "gci | %% {rni $_.Name ($_.Name -replace '120', '121')}"
Otherwise it gets swallowed and you get the error "Expressions are only allowed as the first element of a pipeline."
NB. You are trying to rename every file in the folder, regardless of whether it has 120 in the name or not, this is horrible. Follow Nikhil Gupta's suggestions on how to avoid doing that.
You could have been a little more specific. I'm making assumptions now to try and solve your issue -
You want to rename all the files with 120 in the name to now have 121.
You want to do it in a specific directory but want to run the script from any location on the cmd.
The current script would run in any directory, get all the child items in that directory and replace 120 with 121. It wouldn't work if the name doesn't have 120.
Based on this I suggest 2 modifications -
Add a filter while gci to get only the items with 120 in the name.
Add a first line to go to the directory you need the script to run under.
Here is the sample code -
Set-location <dir>
gci -Filter "*120*" | % {rni $_.Name ($_.Name -replace '120', '121')}
Related
I'm working on creating a batch script which will allow me delete files with the same name and an appended ascending number; for example:
fileName.txt
fileName (1).txt
fileName (2).txt
fileName (3).txt
fileName (4).txt
fileName (5).txt
fileName (6).txt
fileName (7).txt
etc....
Below is the code I came up with, but it only deletes the file name, without the appended number in the parenthesis.
#echo off
:: Change to the Downloads directory
cd %UserProfile%\Downloads
:: Deletes files
Del Awesome-Kicks-Test_File-Run.txt
All of these file are saved in my Downloads directory.
Could you please direct me on how best to go about deleting these files?
Since you are on Windows, you should have access to PowerShell. PS has much better support for these types of operations, and is available on all versions of Windows in common use.
One method is to use a regular expression to find all of the files that match the pattern. Here is a basic one that should work for the example you gave: fileName \(\d+\)
Using PowerShell, you then combine that regular expression with the Get-ChildItem, Where-Object and Remove-Item commandlets.
Get-ChildItem | Where-Object { $_.Name -match 'fileName \(\d+\)' } | Remove-Item
I use an old program that went out of business, it creates a folder and inside of that "root" folder it creates other folders inside of that folder it creates a rar file of the output from the program that ran.
Root
Folder
zipfile
Folder
zipfile
Note that inside of the Root is where there are over 400 folders and each has a zip file inside I need to unrar.
The folder is based on time it was run and this program runs anywhere from 2 times per minute to 6 times a minute so it creates a new folder in the "root" folder based on the time it ran.
To see the information, I need to unrar the file it made in that folder.
Problem, I have over 400 folders inside of a central folder, that has to have all the files unrared to the folder they are currently in.
I know WinRar has an unrar here function, and I have generated a text file that has the directory listing of each folder I need to unrar. One folder per line.
Basically I need a batch file that will go to each folder, do a unrar here and move on to the next folder.
Any help available? I am on a Win10 Home system and have my registered version 5.80 of WinRAR. I am not a Powershell user, I am learning it starting today, I did use PowerShell to generate the txt file with the directory listing though.
(Get-ChildItem -Recurse -Filter "zip").FullName | Out-File d:\pattern.txt
So I am not totally clueless.
Thank you.
Responding to Campo, I use WinRar to handle Zips as well as Rars, I do not find I need a zip extractor when I have WinRar installed.
The reason I asked about the extension in my comments is because you said that you'd already used powershell to create a filelist using Get-ChildItem, and wanting to start learning it.
As you said you were using PowerShell in Windows 10, I expect that you have, PowerShell v5.0+. This therefore, is a single line for a PowerShell script or to enter directly at the PowerShell Prompt, which should unzip each of your .zip files directly without introducing a third party utility, like WinRAR.
Please change the -Path string according to your specific location.
Get-ChildItem -Path "C:\Users\Frank\Root" -Filter "*.zip" -File -Recurse | ForEach-Object { Expand-Archive -Path $_.FullName -DestinationPath $_.DirectoryName -Force }
You didn't clarify whether you wanted to delete the zip file once you've unarchived it, so if you want that functionality, for the purpose of this exercise you could simply append a deletion command:
Get-ChildItem -Path "C:\Users\Frank\Root" -Filter "*.zip" -File -Recurse | ForEach-Object { Expand-Archive -Path $_.FullName -DestinationPath $_.DirectoryName -Force; Remove-Item $_.FullName }
Please note that the example is only a starting point for you. When you learn more, you can add robustness to it, to prevent for example, deleting a zip file if its extraction failed, and perhaps what to do in the event of errors etc.
I am trying to create a batch file that I can use to type in a name of a folder and search multiple directories, then display the results in a new window. Example: I want to search for "tcash" in 3 separate directories, ie; \vm-xa01\users, vm-xa02\users and vm-xa03\users. How can I do this?
The original question had Powershell tag, so the answer is Powershell. For cmd (batch) script, I'd strongly suggest you to move into Powershell anyway. It's 2018 and cmd scripts require lots of tweaking.
In Powershell, there's a built-in cmdlet Out-GridView that might be suitable. For example, to display all txt files in c:\some\path and its subdirectories requires just a few commands. Like so,
gci c:\some\path -Recurse | ? { $_.extension -eq ".txt" } | ogv
First off, get a recursive list of all files
gci c:\some\path -Recurse
Then select those that have extension .txt
| ? { $_.extension -eq ".txt" }
Finally, pass the results to out-gridview aka ogv
| ogv
I also think PowerShell is the better script language for your task.
You can do a dir/Get-ChildItem with ranges [1-3] similar to a Regular Expression, so:
Get-ChildItem "\vm-xa0[1-3]\users\tcash" -File -Recurse | Out-Gridview
should enumerate all matching files and display in a gui window.
Good day,
in a specific directory under Win 8.1, I have these hundreds of text files with the extension *.xml, representing a Web site.
In each and every of those files there is exactly one occurence of a certain tag with a known content, say <tag>old</tag>.
In all these pages, this specific text needs to be replaced by <tag>new</tag>. Subdirectories exist, but they do not need to be examined.
How would I automate this task? (I am not familiar with the PowerShell, don't think I've ever used it, but would that be heading into the right direction? If not - apologies for the misleading tag.)
Thanks in advance!
Try this PowerShell script.
$myFiles=get-childitem C:\Folder *.xml -rec
foreach ($file in $myFiles)
{
(Get-Content $file.PSPath) |
Foreach-Object {$_ -replace "<tag>old</tag>", "<tag>new</tag>"} |
Set-Content $file.PSPath
}
check replacer.bat
for %%# in (*.xml) do (
call replacer.bat "%%~f#" "<tag>old</tag>" "<tag>new</tag>"
)
I am renaming several hundred files, all which vary with an item ID and then a bunch of text after. For example...
BBAT300_abcdefg.xls
BBAT400_abcdefg.xls
I need to delete everything from the underscore, and including the underscore on, so the result is this:
BBAT300.xls
BBAT400.xls
I found this bit of code earlier...
Get-ChildItem -Name -Filter *.xls | foreach {[Regex]::Match($_,"^[^_]*").Value}
and it appears to work, but I can't get it to actually rename the files. My knowledge of scripting is little to none, so this may be an easy fix, I just can't seem to find it. Powershell will show the results in powershell, but not actually rename the files.
You can just pipe this line to the rename item command:
Get-ChildItem -Filter *.txt | Foreach-Object -Process {
$NewName = [Regex]::Match($_.Name,"^[^_]*").Value + '.txt'
$_ | Rename-Item -NewName $NewName
}
EDIT: Changed it to support any location