Batch file that will delete files that are older than 6 months, but will exclude files listed in a separate text file - batch-file

Just wanted to ask for help in batch file. I need to have a text file where the file names of excluded files would be stored in the deletion of files with 6 months above date.
Inside list.txt are trial.csv, trial2.csv which are older than 6 months but should be excluded in the deletion since it is in my list.
I have this code but can't seem to make it work. Please help
#echo off
set exclude_file=C:\Users\Desktop\Test\list.txt
set directory=C:\Users\Desktop\Test
forfiles /p %directory% /s /m *.* /c "cmd /c if #fdate < %date% -180 and not #isdir == true (find /i ""#fname"" < %exclude_file% >nul || del /q #path)"
pause

If you are okay with using Powershell, try this. Would recommend using a -whatif on the remove-item line for testing. Use at your own risk...
$protectedFiles = Get-Content -Path "C:\Users\Desktop\Test\list.txt" | Where {$_}
$oldFiles = Get-ChildItem -Path "C:\Users\Desktop\Test" -File -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.LastWriteTime -lt (Get-Date.AddMonths(-6)}
Foreach($oldFile in $oldFiles){
If ($protectedFiles -NotContains $($_.Name)){Remove-Item $_ -Force}
}

Related

batch script to rename the most recent file in all subfolders?

#echo off
for /f %%i in ('dir /b /a-d /od /t:c "*.pdf"') do (
set LastFileCreated=%%i
)
echo The Last File Created is %LastFileCreated%
pause
:: ren %LastFileCreated% "decs365.pdf"
pause
all I have is this script, but unfortunately it needs to be copied in each and every sub folder, thus defeating the purpose, and it wont even rename the files. Is there any way to add a specified path "D:\Monthly Report" and have it rename the most recently created file in all of the sub folders to "decs365"
I'd suggest you leverage powershell.exe, from your batch-file for this task:
#%__AppDir__%WindowsPowerShell\v1.0\powershell.exe -NoProfile "Get-ChildItem -Filter '*.pdf' -File -Recurse | Sort-Object CreationTime -Descending | Select-Object -First 1 | Rename-Item -NewName 'Decs365.pdf'"
Obviously, if you're not running the command in the same working directory, as you are in your question, you'd need to add that directroy to the command above, e.g. Get-ChildItem -Path 'C:\MyDirectoryPath' -Filter …

forfiles modified files excluding newly created

I am trying to write code that will allow me to identify files in a folder that have been modified since the beginning of the month, but that are not newly created (signifying a revision change). Outputting the number of changed files is more important than the name of the modified files, but it can be either.
I have tried to use forfiles to achieve this, but am unable to figure out how to do this without it also listing newly created files.
I have thought that maybe searching for files created before the beginning of the month yet modified within the last month might be the answer, but am unsure how to do this. My code so far still shows newly created files.
#echo off
REM set revisions folder path
set revisions="C:\Users\nlehman\Desktop\New folder (3)\\"
forfiles /P %revisions% /S /D +08/01/2019 > "Revisions last 30days.txt"
I will make a SWAG and think that you want to identify files written in the current month, but were created earlier than the last time they were written. Is that close?
Place all four (4) files in the same directory. This assumes that if the difference between the creation time and last write time is less than one (1) second, that there has not been a revision.
=== revs.bat
#powershell -NoLogo -NoProfile -File "%~dp0revs.ps1"
=== revs.ps1
$RevDir = 'C:\Users\nlehman\Desktop\New folder (3)'
$CloseEnough = New-Timespan -Seconds 1
Get-ChildItem -File -Recurse -Path $RevDir |
Where-Object {
($_.LastWriteTime -ge (Get-Date (Get-Date) -day 1 -hour 0 -minute 0 -second 0)) -and
(($_.LastWriteTime - $_.CreationTime) -gt $CloseEnough)
}
=== revsnot.bat
#powershell -NoLogo -NoProfile -File "%~dp0revsnot.ps1"
=== revsnot.ps1
$RevDir = 'C:\Users\nlehman\Desktop\New folder (3)'
$CloseEnough = New-Timespan -Seconds 1
Get-ChildItem -File -Recurse -Path $RevDir |
Where-object {
($_.LastWriteTime -ge (Get-Date (Get-Date) -day 1 -hour 0 -minute 0 -second 0)) -and
(($_.LastWriteTime - $_.CreationTime) -lt $CloseEnough)
}
This is going to hurt the eyes of everyone who reads it as it is quite possibly the absolute worst coding on the history of this site, but it works for its purpose, and is the best I can currently do. I am still learning this stuff, and although this does work, I really would have liked to know how to put my results into variables so I did not have to do it the way I did with .txt files...
#echo off
setlocal enabledelayedexpansion
set revisions="C:\Users\nlehman\Desktop\New folder (3)\\"
dir %revisions% /T:C /A-D /O:-D > %revisions%"creation date.txt"
dir %revisions% /T:W /A:-D /O:-D > %revisions%"modified date.txt"
findstr /vig:"C:\Users\nlehman\Desktop\New folder (3)\creation date.txt" "C:\Users\nlehman\Desktop\New folder (3)\modified date.txt" > "C:\Users\nlehman\Desktop\New folder (3)\difference.txt"
findstr /b "08/" difference.txt > "rev changes.txt"
find /v /c "" "rev changes.txt" > revs.txt
del %revisions%"creation date.txt"
del %revisions%"modified date.txt"
del %revisions%"difference.txt"
type "rev changes.txt" "revs.txt" > "revisions.txt"
del %revisions%"rev changes.txt"
del %revisions%"revs.txt"

How to find folders that containt a certain string using CMD?

I need to find the path of every folder that contains the words "test" or "Test" or "TEST" in a specific location. The file tree is huge.
This is to remove every folder that contains "test". I've tried using
the findstr function.
findstr /i "test"
I expect to get every folder path that contains "test"
The list of directories can be generated and iterated over using a FOR loop. When you are satisfied that the correct directories will be deleted, remove the echo from the line containing rmdir.
#echo off
pushd \
for /f "delims=" %%a in ('dir /s /b /a:d "*test*"') do (
echo if exist "%%~a" (rmdir /s /q "%%~a")
)
popd
If you wanted to push ahead into Powershell, which Microsoft says is the future, something like this might work. When you are satisfied that the correct directories will be removed, remove the -WhatIf from the Remove-Item cmdlet.
=== Remove-TestDirectories.ps1
$previousdir = ":" # set to impossible filesystem name
Get-ChildItem -Directory -Recurse -Path "C:\" -Filter "*test*" -Force -ErrorAction SilentlyContinue |
Sort-Object -Property FullName |
ForEach-Object {
#"{0} and {1} and {2}" -f #($previousdir, $_.FullName, $_.FullName.StartsWith($previousdir))
if (-not $_.FullName.StartsWith($previousdir)) {
$previousdir = $_.FullName
if (Test-Path -Path $_.FullName) { Remove-Item -Path $_.FullName -Recurse -WhatIf}
}
}
This can be run from a cmd.exe shell.
powershell -NoLogo -NoProfile -File Remove-TestDirectories.ps1

Rename folders, subfolders, and files

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)
}

How to use batch file to append text to filename?

I've created a batch file to move files that are over 30 days old to an archive folder. I would also like to append a string of text to the end of the files that are moved. Here is what I have for moving the files older than 30 days:
robocopy "C:\...\Data" "C:\...\Archives" /move /minage:30
That part is working great. Any advice on the best way to add a string of text such as "XYZ" to the end? I.E. datafile_XYZ.txt
Thank you in advance for any help!
This could be accomplished with a one-line PowerShell command:
powershell "Get-ChildItem C:\...\Archives\*.* | Where-Object {$_.Name -notlike '"*_XYZ.*'"} | Foreach-object {Rename-Item -Path $_.FullName -NewName ($_.name -replace '\.', '_XYZ.')}"
forfiles /d -30 /m *txt "cmd /c ren #file #fname_xyz.#ext"
more info - http://ss64.com/nt/forfiles.html

Resources