Writing a batch utility to archive files on Windows Server 2008 R2 - batch-file

I need to write a command line (PowerShell or DOS) utility that will
archive all files created in between specified dates present in folder
X and store them as a .zip package in the same folder.
This utility will be scheduled into windows scheduler where arguments like to and from dates, store location will be provided to it and it will run at specified duration for e.g. at 12:00 noon daily.
Is it possible to write it as a batch .bat file?
Are there any built-in functionalities inside windows to zip files or I would need to use a third party program like 7-Zip etc for it.
I am not looking for any spoon feeding but just a direction, can anyone guide me to a tutorial or something. Both DOS based and PowerShell based solution would work for me.
Please help me out with this.
Thank you.

I would go for PowerShell.
With PowerShell you can easyly build and compare dates with the Get-Date commandlet and comparison operators. You could try something like:
$folderPath = 'C:\Temp'
$date1 = Get-Date '2014-05-01'
$date2 = Get-Date '2014-05-31'
foreach( $item in (Get-ChildItem $folderPath) )
{
if( $item.LastWriteTime -ge $date1 -and $item.LastWriteTime -le $date2 )
{
# Compression step
}
}
As for compression you have several options like stated in this question.
And for the script parameters you can check this blog article.

Here is a batch file that builds on Cristophe C's powershell script
It takes a folder and two dates on the command line and writes the last-modified filenames from date1 to date2 into a text file called daterange.txt
Some code can be added to zip up the files if further details are added to the question.
#echo off
if "%~3"=="" (
echo "%~0" "c:\folder" yyyy-mm-dd1 yyyy-mm-dd2
echo(
echo( This returns last-modified files in the folder from the two dates inclusive
echo( and puts them in a file called "daterange.txt"
echo(
echo( Requires Powershell V3+ (Powershell scripting also needs to be enabled^)
echo(
pause
goto :EOF
)
set "file=%temp%\psdaterange.ps1"
(
echo( $folderPath = '%~1\'
echo(
echo( $date1 = Get-Date '%~2'
echo( $date2 = Get-Date '%~3'
echo(
echo( foreach( $item in (Get-ChildItem -file $folderPath^) ^)
echo( {
echo( if( $item.LastWriteTime -ge $date1 -and $item.LastWriteTime -lt $date2.AddDays(1^) ^)
echo( {
echo( Write-Host $folderPath$item
echo( }
echo( }
) >"%file%"
powershell "%file%" > "daterange.txt"
del "%file%"

THere is Compress-Archive utility available in powershell 5.0.
# Create a zip file with the contents of C:\Stuff\
Compress-Archive -Path C:\Stuff -DestinationPath archive.zip
# Add more files to the zip file
# (Existing files in the zip file with the same name are replaced)
Compress-Archive -Path C:\OtherStuff\*.txt -Update -DestinationPath archive.zip
# Extract the zip file to C:\Destination\
Expand-Archive -Path archive.zip -DestinationPath C:\Destination
See this answer for more details:
How to create a zip archive with PowerShell?

Related

batch-script to replace dots in foldernames with spaces

a user of mine is having problems with syncing cloud to local workstation. he is having lots of folders in a deep (10+) folder structure pattern and every folder is containing at least three dots ("xy.asdf.qwer $generic descriptor").
so now there is big foobar. online everything works fine, new files can be created and edited as expected. but the synced files keeps crashing on windows 10 enterprise and explorer warns with "bad foldername" and stuff. so i allowed long folder names (260 chars max.... seriously?) via GPO for user and i thought "well done. problem solved" ... but no... synced local files are still having trouble... so i allowed same option via regedit. same same. explorer keeps complaining.
so i decided to change folder names and remove the dots and replace them with spaces. so folder "xy.asdf.qwer $generic descriptor" will be "xy asdf qwer $generic descriptor". user says it's fine so i wrote a batch to rename folders. sry, my powershell is really bad. but if u know a solution in powershell it is appreciated and fine as well.
#echo off
setlocal enabledelayedexpansion
set "leer= "
set "punkt=."
call :rekursion
goto :eof
:rekursion
for /D %%d in (*) do (
set name=%%~nxd
ren "%%d" "!name:%punkt%=%leer%!"
cd %%d
call :rekursion
cd ..
)
exit /b
batch is working fine, but keeps throwing errors and telling me "not allowed" ... what is wrong with it? why is it working but complaining? what am i missing? all rights are set proper (full access...)
[sry for bad English...]
This PowerShell script will do what you want. If you are on a supported Windows platform, PowerShell will be available.
I would not want SPACE characters in directory or file names, but that is your choice. When you are satisfied that the names would be changed correctly, remove the -WhatIf from the Rename-Item command.
#Requires -Version 3
$BaseDir = 'C:\src\t'
Get-ChildItem -Recurse -Directory -Path $BaseDir |
Sort-Object -Descending -Property FullName |
Where-Object { $_.Name -match '\.' } |
ForEach-Object {
$NewName = $_.Name -replace '\.',' '
Rename-Item -Path $_.FullName -NewName $NewName -WhatIf
}
The order is the issue. You are renaming the folder BEFORE you try to change directories. It works because after you rename the folder, the loop will pick up the new folder name, but is much less efficient. I was seeing errors on the 'cd' line. This works for me and is a bit simpler:
#echo off
setlocal enabledelayedexpansion
set "leer= "
set "punkt=."
:rekursion
for /D %%d in (*) do (
pushd %%d
call :rekursion
popd
set name=%%~nxd
ren "%%d" "!name:%punkt%=%leer%!"
)

Rename multiple pdf files after reading corresponding text files present in different folder using bat script

PROBLEM
I am working on a bat script which should be able to read 1000 of text files from a location say Z:/Demo/Text and after reading the stored values the script is able to rename the corresponding pdf files present at say Z:/Demo/PDF. The text files are named and read in the following manner: SomeDate_Part1.txt, SomeDate_Part2.txt....
And the PDF files possess the same attribute just the file extension is different.
Renaming logic:
If the value stored in the SomeDate_Part1.txt file is AAA then the corresponding PDF file ie SomeDate_Part1.pdf should be renamed as CGI1_filename.pdf and if the stored value is BBB then it should be renamed as CGI2_filename.pdf.
I wrote a few lines and was able to successfully read all the text files from the folder. The code I wrote is:
#echo off
for %%x in (\Demo\Text\*.txt) do (
for /f "usebackq delims=" %%a in ("%%~fx") do (
if "%%a"=="AAA" echo %%a
if "%%a"=="BBB" echo %%a
)
)
pause
How can I solve the remaining issue?
#echo off
setlocal EnableDelayedExpansion
set "AAA=1"
set "BBB=2"
for %%x in (\Demo\Text\*.txt) do (
for /f "usebackq delims=" %%a in ("%%~Fx") do (
ren "\Demo\PDF\%%~Nx.pdf" "CGI!%%a!_%%~Nx.pdf"
)
)
pause
This code is practically a copy of the original with just two differences:
The values of AAA and BBB are set to 1 and 2, respectively. These values are stated in the question decription.
The two if commands that just display the values in the text files are changed by the desired ren command, as requested in the question description. In the ren command, the location of the .pdf file is set to \Demo\PDF as stated in the question. The new part of the name is comprised by CGI!%%a!_. The %%a contain the value stored in the text file that is AAA or BBB accordingly to the description. In this way, the !%%a! part becomes !AAA! or !BBB! that is replaced by the value of AAA or BBB via delayed expansion, so the new file name is CGI1_SomeDate_Part1.pdf or CGI2_SomeDate_Part2.pdf as requested in the question.
If you are willing to push ahead into PowerShell, this code might do what you want. I have not tested it. When you are confident that the files will be renamed correctly, remove the -WhatIf from the Rename-Item cmdlet.
Save this script as Rename-PdfFiles.ps1.
Get-ChildItem -File -Path '\Demo\Text' -Filter '*.txt' |
ForEach-Object {
$fn = $_.BaseName
$pdfname = "\Demo\Text\$($fn).pdf"
if (Test-Path -Path $pdfname) {
$mark = Get-Content -Path $_
if ($mark -eq 'AAA') { $prefix = 'CGI1' } else { $prefix = 'CGI2' }
Rename-Item -Path $pdfname -NewName "$($prefix)_$(fn).pdf" -WhatIf
}
}
Run it from a cmd shell using:
powershell -NoProfile -File .\Rename-PdfFiles.ps1
If you cannot get past making a .bat file, this might work. I have not tested this either. If it outputs the correct RENAME commands, remove the echo at the beginning of the line.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%x IN ('\Demo\Text\*.txt') DO (
SET "FN=%%~nx"
SET "PDFNAME=\Demo\Text\!FN!.pdf"
IF EXIST "!PDFNAME! (
SET /P "MARK=" <"%%~x"
IF "!MARK!" == "AAA" ( SET "PREFIX=CGI1" ) else ( SET "PREFIX=CGI2" )
echo RENAME "!PDFNAME!" "!PREFIX!_!FN!.pdf"
)

Filename and path extraction - multiple folders

I have a set of folders in a drive and need to extract the path and filename of all of the files who have similar names (i.e., index_lms.htm or index*.htm). I need these to go into a csv file, which I will manipulate and use in a mass upload template. Is this possible through cmd shell or a batch file? (It's been a while since I tried writing these.)
Today the size of the task got worse....... I now have 1000 English courses, and translated versions in German, Turkish and Russian. So I really needed a batch solution to extract these pathnames - thank you.
One other issue arose in the the filename cannot have spaces and I see that all of them have multiple spaces in their filenames. Is this easy to edit as the paths/filenames are read?
Quick answer to Gung - the files are loaded into an LMS system and the target file for elearning is normally index.html or index_lms.html or index_html5.html. However the LMS also serves up documents (my current issue) in my case they are all pdf with a standard naming convention
This batch will iterate the given folders and recursively search them for any file beginning with index and create a csv with a header and the columns File, Path and PathFile.
#Echo off
SetLocal EnableExtensions
( Echo "File","Path","PathFile"
For %%A in (
"X:\Test\"
"Y:\Home\Customer\"
"Z:\Users\UserName\"
) Do Call :Search "%%~A"
) > "%~dpn0.csv"
Goto :Eof
:Search
For /R %1 %%B in (index*.htm*) Do Echo "%%~nxB","%%~dpB","%%~fB"
The output file will have the same drive, path and name as the batch file but the extension .csv
This will create file out.csv. Substitute your own dir pattern match.
del 2>nul out.csv
for /f "delims=" %%f in ('dir/s/b c:\index*.htm') do <nul set /p =%%f,>>out.csv
Here is another way to do it in PowerShell.
PS C:\src\t> type .\f2csv.ps1
$dirs = 'C:\src\t', 'C:\labs'
foreach ($dir in $dirs) {
Get-ChildItem -File '*.txt' -Recurse |
Select-Object #{Expression={$_.FullName}; Label="filename"} |
Export-Csv -Path '.\f2csv.csv' -Delimiter ',' -NoTypeInformation
}
PS C:\src\t> .\f2csv.ps1
PS C:\src\t> type .\f2csv.csv
"filename"
"C:\src\t\iosloginfo\lognextnum.txt"
"C:\src\t\t\file1.txt"
"C:\src\t\t\file10.txt"
"C:\src\t\t\file2.txt"

Mass Copy and Rename files into same respective directories (CLI/PowerShell)

Say I have a file named api-build009.jar and it exists in multiple directories.
D:\InstallDir\subdir1\
D:\InstallDir\subdir2\subdir21\
D:\InstallDir\subdir3\
D:\InstallDir\subdir4\subdir41\
D:\InstallDir\subdir5\
D:\InstallDir\subdir6\subdir61\subdir62\
D:\InstallDir\subdir7\
D:\InstallDir\subdir8\
I want to backup (and thus rename) the file into the same respective directory as the original file. I want to perform this operation for all directories above (8, in this example), copying the original file and then rename it to api-build009.jar.bak.
D:\InstallDir\subdir1\api-build009.jar.bak
D:\InstallDir\subdir2\subdir21\api-build009.jar.bak
D:\InstallDir\subdir3\api-build009.jar.bak
D:\InstallDir\subdir4\subdir41\api-build009.jar.bak
D:\InstallDir\subdir5\api-build009.jar.bak
D:\InstallDir\subdir6\subdir61\subdir62\api-build009.jar.bak
D:\InstallDir\subdir7\api-build009.jar.bak
D:\InstallDir\subdir8\api-build009.jar.bak
How can I perform this process using Windows CLI or PowerShell?
Thank you kindly in advance.
Once you write a file - sounds like the same file, and then you write backup the file in the same folder. Are these different versions or copies of the same file.
These scripts will copy the files to same name and location with .bak extension
Batch
#Echo off
PushD "D:\InstallDir"
For /f "delims=" %%A in (
'Dir /B/S api-build009.jar'
) Do Echo Copy "%%~fA" "%%~fA.bak"
Popd
PowerShell
Get-ChildItem -Path D:\InstallDir -File -Filter api-build009.jar|
ForEach { Copy-Item $_.FullName -Destination "$($_.Fullname).bak" -whatif}
If the output looks ok remove the echo in the batch / -whatif in the script

How to find files NOT containing a defined text and output their names into a file?

I am having an application folder with sub-folders and thousands of files in it. I want to write a batch script which lists all the files which DO NOT contain particular text, say SAMPLE_TEXT and redirect output to a file. Please help with the script.
Inspired by http://tobint.com/blog/powershell-selecting-files-that-dont-contain-specified-content/ this powershell worked well for me;
Get-ChildItem -include *.sql -recurse | ForEach-Object { if( !( select-string -pattern "USE " -path $_.FullName) ) { $_.FullName}} > FilesMissingUse.txt
In my case I was searching for database scripts (.sql files) which were missing "USE " string.
This may help you - launch it in the top level folder.
#echo off
(for /r %%a in (*) do find "SAMPLE_TEXT" "%%a" >nul || echo %%a)>file.log
#echo off
findstr /S /M /V "SAMPLE_TEXT" *.* > output.txt
With grep you can use
grep -L Font *.pdf > list_of_files.txt
The -L switch returns only files that do not contain the string "Font."

Resources