So I have this little problem...
(Windows 10 Education N x64)
I am a GoldSrc engine developer and i am trying to achieve the
following thing with Batch script or PowerShell, to do that automated
task by itself instead of me manually picking every damn folder,
eventually to spare time. :)
I am having directory structure as following:
Main(root) folder names "GoldSrc" is located at "Desktop"
So it goes like this:
Absolute Path:
Image from TREE VIEW:
[Main folder]
C:\Users\Andrej Poženel\Desktop\GoldSrc
[Source directory to copy from with recursive subdirectories]
C:\Users\Andrej Poženel\Desktop\GoldSrc\prefabs
[Directory to copy to]
C:\Users\Andrej Poženel\Desktop\GoldSrc\Maps
I want to lookup into subfolder named "prefabs" and search all
subfolders in that directory for files that have file extension .map
AND .rmf, so both filters together and copy them from its source
location [../GoldSrc/prefabs/like_100_folders_here] to "GoldSrc"
subdirectory named "Maps", everything shown on picture)
So i want the things look like this after this process:
C:\Users\myusername\Desktop\GoldSrc\Maps: blabla.map bleble.rmf
bleble.rmf cacac.rmf adasdad.map ...
and not each file in its own directory like it is in source dir...
Thanks in advance
pushd "C:\Users\myusername\Desktop\GoldSrc"
for /f "delims=" %%a in ('dir /s /b /a-d .\prefabs\*.map .\prefabs\*.rmf') do ECHO copy "%%a" ".\maps\"
popd
Should execute this.
First move to the required subdirectory, then perform a directory scan including subdirectories in basic form and excluding directorynames. For each returned line matching either of the filespecs, assign the name found to %%a, then copy that file to the required subdirectory.
then return to the original directory.
The commands generated will simply be echoed to the console. To actually execute the command (after checking), remove the ECHO keyword.
Note that this is a batch file, and not intended to be executed directly from the prompt.
If you want to do it the Powershell way, you can use the below code
gci "C:\Users\Andrej Poženel\Desktop\GoldSrc\prefabs" -filter *.map | %{
copy-item -Path $_.FullName -Destination "C:\Users\Andrej Poženel\Desktop\GoldSrc\Maps"}
gci "C:\Users\Andrej Poženel\Desktop\GoldSrc\prefabs" -filter *.rmf | %{
copy-item -Path $_.FullName -Destination "C:\Users\Andrej Poženel\Desktop\GoldSrc\Maps"}
or
gci "C:\Users\Andrej Poženel\Desktop\GoldSrc\prefabs" -recurse | ?{
!$_.PsIsContainer -and $_.Extension -match "map|rmf" } | %{
copy-item -Path $_.FullName -Destination "C:\Users\Andrej Poženel\Desktop\GoldSrc\Maps"}
Related
I running an xcopy command to transfer from one file to the other.
xcopy /s "c:\users\documents\thisfile.txt" "d:\otherfiles\1.2.1"
I'd like to be able to just copy the file into the most recent folder in the otherfiles directory rather than hard coding it every time a new version folder is created. These are versions numbers and these tend to just increase.
Is this entirely possible?
If you wanted to do this in PowerShell, it is possible. This would require PowerShell 3.0 or higher. It can be done with 2.0, but would require changes. Hopefully, you are on or can upgrade to a modern-day version of PowerShell.
When you are confident that the file will be copied correctly, remove the -WhatIf from the Copy-Item cmdlet.
$fn = 'C:/src/t/xxx.txt'
$destbasedir = 'C:/src/t/lastdir'
Get-ChildItem -Directory -Path $destbasedir |
Sort-Object -Property Name |
Select-Object -Last 1 |
ForEach-Object { Copy-Item -Path $fn -Destination $_.FullName -Whatif }
This could be put into a .bat file script.
SET "FN=C:\src\t\xxx.txt"
SET "DESTBASEDIR=C:\src\t\lastdir"
powershell -NoProfile -Command ^
"Get-ChildItem -Directory -Path %DESTBASEDIR% |" ^
"Sort-Object -Property Name |" ^
"Select-Object -Last 1 |" ^
"ForEach-Object { Copy-Item -Path "%FN%" -Destination "$_.FullName" -Whatif }"
Ok, it is possible to check the versions of the directories, but that will take a bit more code as we cannot simply remove the dots to get a numeric value and compare to the next. The reason being, considering versions 1.2.3 and 1.23 if we remove the dots to make it a matchable numeric value, both these will end up being being 123 therefore each version section would need to be tested.
However, based on your comments to my questions, you create new versions as folders, and therefor it ia sortable by date, so simply run a dir command and sort by created date. It will set the latest folder as the variable you need:
#echo off
for /f "delims=" %%i in ('dir /b /ad /o:d D:\otherfiles') do set "myvar=%%i"
xcopy /s "c:\users\documents\thisfile.txt" "d:\otherfiles\%myvar%"
I´m taking pictures with my mobile phone sometimes in JPG only, but sometimes in RAW. When shooting RAW, mobile phone actually stores two files (filename.jpg and filename.dng).
I would like to write a script which would search defined folder and delete all JPGs which have same filename like the DNGs (RAW).
Example - folder has following files:
IMG_20170625_105228.dng
IMG_20170625_105228.jpg
IMG_20170625_105326.jpg
IMG_20170625_105337.jpg
IMG_20170625_105350.dng
IMG_20170625_105350.jpg
Script should delete:
IMG_20170625_105228.jpg
IMG_20170625_105350.jpg
Iterate over the .dng files and if a like-named .jpg file exists, delete it. When you are satisfied that the correct files would be deleted, remove the ECHO from the DEL command.
PUSHD "C:\the\dir\containing\pics"
FOR /F "usebackq tokens=*" %%f IN (`DIR /B "*.dng"`) DO (
IF EXIST "%%~nf.jpg" (ECHO DEL "%%~nf.jpg")
)
POPD
If, for whatever reason, you wanted to do this in PowerShell, you could do something like this. When the correct files are being removed, remove the -WhatIf from the Remove-Item command. I would be interested to hear from anyone about a better way to do this in PowerShell.
$picdir = 'C:\dir\path\to\pics'
Get-ChildItem -Path $picdir -File -Filter '*.dng' |
Where-Object { Test-Path -Path "$($_.DirectoryName)/$($_.BaseName).jpg" -PathType Leaf } |
Select-Object #{Name="Path";Expression={"$($_.DirectoryName)\$($_.BaseName).jpg"}} |
Remove-Item -WhatIf
I did the following script in PowerShell:
(Get-Content text\text.txt).replace('ABC', 'abc') | Set-Content text\text.txt
it works as expected...
it reads the contents of a file and replaces a particular character sequence by another seguency...
but, I need that script identify multiple files with different names in others possibles subdirectories of the same initial directory.
dir01\file_name.abc
dir01\filename.def
dir01\dir02\fi-le_na-me.ghi
dir01\dor02\fi_le-na_me.jkl
dir01\dir02\dir03\f-i-l-e_n-a-m-e.mno
etc...
I do not know which will be the names of the files nor the directories too!
In msdos I use the following expression to go from file to file:
for %%F in (*.*) do ("winRAR.exe" "%%F")
this batch, compresses file by file... its only a sample!
I do not know how to identifying file by file in PowerShel... Could someone help me with that?!
Just use Get-ChildItem and pipe the output into your command. You can tell Get-ChildItem to recurse directories using -recurse and only return files with -File:
Get-ChildItem dir01 -recurse -file |
foreach{(Get-Content $_.FullName).replace('ABC', 'abc') | Set-Content $_.FullName}
I am new to coding / programming and trying to create a simple robocopy routine that automates the duplication of a template project folder from one location to the main project drive, then renames the "00-000" portion of the folder (which is always at the beginning of the name) and contained subfolders and files based on a user specified variable. Here is what my robocopy routine looks like.
echo off
robocopy "C:\Program Files\Autodesk\ACAD_Config\00-000-NewProject" "T:\Projects" /xd Dfsrprivate /s /e /W:0 /xd DfsrPrivate /r:0 /np
The rename portion is where I get lost. Once the 00-000-NewProject folder has been created on the T:\ drive, it should be time to rename the folder and contained sub-folders and files.
For example,
Routine prompts to set variableA "Enter project number:"
User enters variableA definition, "EP-001"
Routine verifies changes that are about to be made "The Project Number for all folders and files will be renamed to: 'EP-001' is this correct Y/N ?"" (y = confirm changes and on to step 4. n = reenter project number)
This routine replaces any instance of (00-000) contained within the 00-000-NewProject folder with VariableA
Is my idea possible with windows CMD? I would like to avoid installing any 3rd party applications as updates and maintenance can get hairy in a 100 person firm. Any help would be greatly appreciated but further explanation of any suggested code would be most useful in teaching myself how to program. Thank you in advance!
I believe this is what you are trying to do, but as #Guildencrantz mentions, you may need to clarify further about your project structure, files, did you mean file names only, directories, etc.
Example batch file
To use, rename d:\test to your t: directory, remove the echo statements so commands execute, etc.
#echo off
setlocal enabledelayedexpansion
set variableA=EP-001
set newfolder=%variableA%-NewProject
echo robocopy "C:\Program Files\Autodesk\ACAD_Config\00-000-NewProject" "D:\test\Projects\%newfolder%" /xd Dfsrprivate
::: rename all files under T:\Projects\%newfolder% that start with 00-000 prefix with the variableA prefix
for /r D:\test\Projects\%newfolder%\ %%f in (*) do (
::: #echo Found: %%f
set newname=%%f
call set newname=!newname:00-000=%variableA%!
#echo ren %%f !newname!
)
endlocal
Sample Output:
D:\test>rename1.cmd
robocopy "C:\Program Files\Autodesk\ACAD_Config\00-000-NewProject" "D:\test\Projects\EP-001-NewProject" /xd Dfsrprivate
ren D:\test\Projects\EP-001-NewProject\00-000-one.txt D:\test\Projects\EP-001-NewProject\EP-001-one.txt
ren D:\test\Projects\EP-001-NewProject\00-000-two.txt D:\test\Projects\EP-001-NewProject\EP-001-two.txt
I see that this is old. It may not matter now, but it was interesting to work out. The difficult spot was renaming the directories from the furthest leaf back to the root.
$project_base = 'C:/src/t/bn'
$template_dir = "$($project_base)/00-000-NewProject"
$project_name_approved = $false
do {
$pn = Read-Host 'Please enter the new project name'
$new_project_dir = "$($project_base)/$($pn)-NewProject"
if (Test-Path -Path $new_project_dir) {
Write-Host "Project $($pn) already exists. Please choose another project name."
} else {
$ap = Read-Host "Rename new project to $($pn)? (Y/N)"
if ($ap -match '^y') { $project_name_approved = $true }
}
} until ($project_name_approved)
# Create the new project directory and copy template files
New-Item -ItemType Directory -Path $new_project_dir | Out-Null
Copy-Item -Path "$($template_dir)\*" -Destination $new_project_dir -Recurse -Exclude DfsrPrivate
# Rename directories first, from the longest leaf in the tree back to the shortest
$dir_names = Get-ChildItem -Recurse -Directory -Path $new_project_dir |
Sort-Object -Property Length -Descending |
ForEach-Object {
$fn = Split-Path $_ -Leaf
if ($fn -match '^00-000') {
Rename-Item -Path $_.FullName -NewName "$($fn -replace '^00-000', $pn)"
}
}
Get-ChildItem -Path $new_project_dir -File -Recurse |
ForEach-Object {
Rename-Item -Path $_.FullName -NewName $($_.Name -replace '00-000', $pn)
}
I have found a few similar problems on Stackoverflow, and after trying out the solutions, my problem remains unsolved.
Here is my directory structure:
D:\XYZ\Adam Jay\Adam Jay\files.txt
D:\XYZ\Adam Jay\Adam Jay\SomeFolder\
D:\XYZ\Adam Jay\Adam Jay\OtherFolder\Some File.doc
D:\XYZ\Mary Poppins\Mary Poppins\myOtherFile.txt
and I have about 2000 of these.
My goal is to simply cut out the redundant sub-sub folder, following the above structure. Manually, I would simply cut the "sub-sub" folder "Adam Jay" and paste it into XYZ, where-in it will replace or merge with the upper-level "Adam Jay" (moving whatever files and folders with it).
The desired result:
D:\XYZ\Adam Jay\files.txt
D:\XYZ\Adam Jay\SomeFolder\
D:\XYZ\Adam Jay\OtherFolder\Some File.doc
D:\XYZ\Mary Poppins\myOtherFile.txt
I have very little knowledge of batch scripts, and no knowledge of PowerShell. By modifying a script I found here on StackOverflow, I managed to mess things up (luckily, it was a test directory). [The script I played with can be found here:
PowerShell Script to move folders one level up and delete the previous containing folder ]
It would be great if anyone can help me out with this. I would really appreciate it.
Thanks.
This should do it:
#echo off
setlocal enabledelayedexpansion
cd /d D:\XYZ
for /f "tokens=*" %%a in ('dir /b /ad') do (
if exist "%%a\%%a" (
xcopy /E "%%a\%%a\*" "%%a"
rd /s /q "%%a\%%a"
)
)
I'll go the PowerShell route. This has two options, by default it will remove any double folders so...
Z:\XYZ\John Doe\John Doe\My Documents\Stuff\Stuff\ItsAFile.txt
becomes:
Z:\XYZ\John Doe\My Documents\Stuff\ItsAFile.txt
If you only want to get rid of the first duplicate folder comment out the 6th line, and uncomment the 7th. If you don't like the reporting part remove/comment out the Write-Output lines.
$BasePath = "D:\XYZ"
gci $BasePath -recurse | %{
$OriginalFile = $_
If($OriginalFile.PSIsContainer){$FilePath = $_.FullName.ToString().Split('\')}
Else{$FilePath = $_.Directory.ToString().Split('\')}
for($i=1;$i -lt $FilePath.Count;$i++){ #Comment out this line to change to Base Path +2 folders method
# for($i=0;$i -lt $($BasePath.Split('\').Count +2);$i++){ #Uncomment to only affect the first 2 folders past the base path
if($filepath[$i] -and ($FilePath[$i] -ieq $FilePath[$i-1])){
$FilePath[$i-1] = $Null
}
}
($FilePath|?{$_}) -join '\'|%{
if($OriginalFile.PSIsContainer){
If(!($OriginalFile.FullName -ieq $_)){
Write-Output "Moving folder $($OriginalFile.fullname) to $_"
move-item "$($OriginalFile.fullname)\*" $_ -ErrorAction SilentlyContinue
Remove-Item $OriginalFile.fullname -ErrorAction SilentlyContinue}
}else{
If(!($OriginalFile.Directory.ToString() -ieq $_)){
Write-Output "Moving file $($OriginalFile.fullname) to $(Resolve-Path "$_\..")"
move-item $OriginalFile.fullname "$_\.." -ErrorAction SilentlyContinue
}}
}
}
To step through that, it:
Pulls a directory listing of each folder or file in the base path.
For each one it splits up the path based on the backslash character,
excluding file names.
It then steps through each segment comparing each folder to the one
before it in the path (or only steps the first few segments if you
go that route).
If the two sequential folders match it removes the first one.
It then rebuilds the path at the end of that process.
After that it compares the modified path to the original, and if
they are different it moves that item to the modified path.
It does handle files and folders differently, as it uses the .FullName property for folders, and the .Directory property for files.