I am using below batch script to copy .class files from dir sourcedir2 to dir sourcedir1 based on same matched file names.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir1=U:\sourcedir\changeset"
SET "sourcedir2=U:\sourcedir\target"
FOR /f "delims=" %%a IN ('dir /b /s /a-d "%sourcedir1%\*.java" ') DO (
SET "javadir=%%~dpa"
SET "classfile=!javadir:%sourcedir1%=%sourcedir2%!%%~na.class"
IF EXIST !classfile! ECHO COPY "!classfile!" "%%a"
)
GOTO :EOF
Addition to this I wanted to copy .class files which are having filename format as classname$number.class (ex :Action$1.class ,Action$2.class) from dir sourcedir2 to dir sourcedir1.
I tried the change for SET classfile as below but also it will copy files which are not in the format of classname$number.class
SET "classfile=!javadir:%sourcedir1%=%sourcedir2%!%%~na*.class"
Please suggest me Regularexpression to match file names with having only format as classname$number.class or classname.class .
Thank you ..
This PowerShell script copies from sourcedir2 to sourcedir1 based on the filename matching a regex for the class name and any digits before the .class extension. When you are confident that the correct files will be copied, remove the -WhatIf from the Copy-Item cmdlet.
$sourcedir1 = 'C:\src\t\j1'
$sourcedir2 = 'C:\src\t\j2'
Get-ChildItem -Path $sourcedir1 -File -Recurse -Filter '*.java' |
ForEach-Object {
$classname = $_.BaseName
Get-ChildItem -Path $sourcedir2 -File -Filter "$classname*.class" |
Where-Object { $_.Name -match "$classname\$[0-9]*\.class" } |
ForEach-Object { Copy-Item $_.FullName $sourcedir1 -WhatIf }
}
To run this from a cmd shell, put the code above into a file such as copyclasses.ps1 and use:
powershell -NoProfile -File .\copyclasses.ps1
I am able to find the workaround solution with below script. Thank you.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir1=U:\sourcedir\changeset"
SET "sourcedir2=U:\sourcedir\target"
FOR /f "delims=" %%a IN ('dir /b /s /a-d "%sourcedir1%\*.java" ') DO (
SET "javadir=%%~dpa"
SET "classfile=!javadir:%sourcedir1%=%sourcedir2%!%%~na.class"
IF EXIST !classfile! ECHO COPY "!classfile!" "%%a"
SET "innerclassfile=!javadir:%sourcedir1%=%sourcedir2%!%%~na"$"*.class"
IF EXIST !innerclassfile! ECHO COPY "!innerclassfile!" "%%a"
)
GOTO :EOF
Related
I use this script to move a set of files inside folders generated by script
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=C:\Users\Administrator\Desktop\khin\test"
SET "destdir=C:\Users\Administrator\Desktop\khin\test"
SET /a destcount=0
SET /a maxcount=10
SET /a filecount=maxcount
FOR /f "delims=" %%a IN (
'dir /b /a-d "%sourcedir%\*" '
) DO (
SET /a filecount +=1
IF !filecount! geq %maxcount% (
SET /a filecount=0
SET /a destcount +=1
MD "%destdir%\folder!destcount!"
)
MOVE "%sourcedir%\%%a" "%destdir%\folder!destcount!\"
)
GOTO :EOF
What is my problem?
I need always to set a source folder and a target folder
SET "sourcedir=C:\Users\Administrator\Desktop\khin\test"
SET "destdir=C:\Users\Administrator\Desktop\khin\test"
What do I want?
I want just press on batch .bat (is inside into my folder) where files are ready to be moved without set source/target because I have to repeat this operation for other files in other folders as well.
example:
I have 31 files (example). I execute this script and script creates 3 folders. For each folder you find 10 files (except in the fourth folder where you will find 1 file).
To do this, my script need to have source and target to move files. But I want that script generates these folders inside the folder it is in.
If you could do this in PowerShell, it might be something like this. Note that this will -not move the .ps1 script file.
$MaxCount = 10
$FileList = Get-ChildItem -File -Path $(Split-Path -Path $PSCommandPath -Parent) |
Where-Object { $_.Name -ne $(Split-Path -Path $PSCommandPath -Leaf) }
for ($i = 0; $i -lt $FileList.Count; $i++) {
$DirNum = [Math]::Floor($i / $MaxCount)
$DirName = Join-Path -Path $(Split-Path -Path $PSCommandPath -Parent) `
-ChildPath $("Dir" + $DirNum)
if (-not (Test-Path $DirName)) { mkdir $DirName -WhatIf }
Move-Item -Path $Filelist[$i].FullName -Destination $DirName -WhatIf
}
I am having trouble with this script. I'll explain below the codeblock.
#Echo off
pushd "\\server\folder"
SETLOCAL EnableDelayedExpansion
#FOR /F "TOKENS=2" %%A IN ('WHERE /T "testfiles*.*"') DO #(
set fdate123=%%A
echo !fdate123:~5,9!0!fdate123:~0,1!!fdate123:~2,2!
call StringLen !fdate123!
)
pause
:StringLen
Setlocal EnableDelayedExpansion
:: strLen String [RtnVar]
:: -- String The string to be measured, surround in quotes if it contains spaces.
:: -- RtnVar An optional variable to be used to return the string length.
Set "s=#%~1"
Set "len=0"
For %%N in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if "!s:~%%N,1!" neq "" (
set /a "len+=%%N"
set "s=!s:~%%N!"
)
)
Endlocal&if "%~2" neq "" (set %~2=%len%) else echo %len%
Exit /b
What I'm trying to do it get the date modified of the file, and change the format of that date returned to YYYYMMDD. I want the date modified to be appended to the filename. I can have files from multiple days in this folder and each file may have a different date modified date.
Please do not mark this as a duplicate question, because I could not find this approach to doing this here.
I was trying to test for date string length so I can handle dates like 1/1/2019 (length of 8) vs 1/13/2019 (length of 9) vs 10/1/2019 (length of 9) vs 10/22/2019 (length of 10) then using if statements parse the date appropriately with the likes of something like !fdate123:~5,9!!fdate123:~0,1!!fdate123:~2,2! - I have not finished this yet.
I have tried getting the date with dir /T:W testfiles*.* and running a findstr but I don't understand findstr well enough to do that.
I also tried to pull it from forfiles /M BC_Services_Adjustment* /C "cmd /c echo #fdate" and moved on from that as well.
maybe somebody has a better solution, I think mine is a mess right now. Does anybody know how to get the date modified time stamp of every file in a folder, convert it a variable with YYYYMMDD format and then append it into all the files in a folder?
Note: I am not looking for powershell solutions for this question, please do not waste your time posting powershell answers.
Update #2 (5/21/19)
I tried magoo's code, I'm still needing a solution to rename the files.
#echo off
pushd "\\server\folder"
SETLOCAL EnableDelayedExpansion
FOR /F "TOKENS=2" %%A IN ('WHERE /T "*.csv"') DO (
for /f "tokens=1-3delims=/-." %%i in ("%%A") do (
set "mm=00%%i"&set "dd=00%%j"&set "yy=0000%%k"
set "fdate123=!yy:~-4!!mm:~-2!!dd:~-2!"
)
rem echo to test if date modified matches to the right filenames.
echo !fdate123! ^& %%A
rem ren "%%~nxA" "%%~nxA!fdate123!"
)
pause
I have tried with the ren "%%~nxA" "%%~nxA!fdate123!" but it's not finding the file. Probably super simple. If somebody can make magoo's code do a rename instead of just echoing the date I can award out the bounty on this question.
Be sure to specify your extentions so if your bat file is in that directory, it will not also be renamed.
#echo off
pushd "\\server\path123"
SETLOCAL EnableDelayedExpansion
FOR /r %%f IN (*.csv, *.txt) DO SET filedatetime=%%~tf & ren "%%~nf.*" "%%~nf!filedatetime:~6,4!!filedatetime:~0,2!!filedatetime:~3,2!%%~xf
FOR /F "TOKENS=2" %%A IN ('WHERE /T "testfiles*.*"') DO (
for /f "tokens=1-3delims=/-." %%i in ("%%A") do set "mm=00%%i"&set "dd=00%%j"&set "yy=0000%%k"
set "fdate123=!mm:~-2!!dd:~-2!!yy:~-4!"
echo !fdate123!
)
should allow you to construct the data according to your wishes.
The inner if assigns mm, dd and yy as appropriate, using the delimiters specified analysing %%A as a literal. Each is prefixed by an appropriate number of zeroes. The required string is then constructed using substringing selecting the last 2/4 characters of the string, so an 8-character output is obtained.
I use dd/mm/yyyy format and haven't actually tested this method, but manipulating it to your requirements should be obvious, the only issue really being how to handle yy dates as distingct from yyyy dates, if that's a concern.
I figured this out on my own, pure batch solution.
Takes date modified, appends it to any filename in a directory in YYYYMMDD format. I really was overcomplicating it, can't believe I didn't come up with this prior to setting a bounty. lol
pushd "\\server\folder"
SETLOCAL EnableDelayedExpansion
FOR /r %%f IN (*) DO SET filedatetime=%%~tf & ren "%%~nf.*" "%%~nf!filedatetime:~6,4!!filedatetime:~0,2!!filedatetime:~3,2!%%~xf"
Yes, I read that you do not want any PowerShell answers. Please be sure not to select this one as the answer. I did not waste my time writing something for you. This is for someone else who might get some benefit.
[CmdletBinding()]
Param (
[Parameter(Mandatory=$true)]
[string]$CommandName
)
$dirlist = #('.') + ($Env:Path.Split(';'))
$extensions = #('') + ($Env:PATHEXT.Split(';'))
$results = foreach ($dir in $dirlist) {
if (($dir) -and ($dir -ne '')) {
if (Test-Path -Path $dir -ErrorAction SilentlyContinue) {
# The directory path exists.
# Check for presence of the file with any executable extension.
$dirhash = #{}
foreach ($extension in $extensions) {
Get-ChildItem -File -Path $dir -Filter "$CommandName$extension" |
ForEach-Object {
# If the file name is not already in the hash, add it to the hash
# and output it in the pipeline.
if (-not $dirhash.ContainsKey($_.Name)) {
$dirhash.Add($_.Name,1)
$_
}
}
}
}
}
}
$results | ForEach-Object {
Rename-Item -LiteralPath $_.FullName -NewName ($_.BaseName + $($_.LastWriteTime.ToString('yyyyMMdd')) + $_.Extension)
}
UPDATE:
Now that the OP's intent is known, this is a much more simple problem. Once you are confident the files will be renamed correctly, remove the -WhatIf from the Rename-Item cmdlet.
Set-Location -Path '//server/sharename'
Get-ChildItem -File -Filter 'testfiles*.*' |
ForEach-Object {
Rename-Item -LiteralPath $_.FullName -NewName ($_.BaseName + $($_.LastWriteTime.ToString('yyyyMMdd')) + $_.Extension) -WhatIf
}
I believe that the output from robocopy is in a consistent format, so I would suggest this as a possible single line batch-file option:
#PushD "\\server\folder" 2>Nul&&For /F "Tokens=1-4*Delims=/ " %%A In ('RoboCopy . $ testfiles*.* /L /NS /NJS /NJH /NDL /NC /TS')Do #Ren "%%E" "%%A%%B%%C-%%~nxE"
Alternatively, based upon your edited additional example code, this is more likely what you need:
#PushD "\\server\folder" 2>Nul&&For /F "Tokens=1-4*Delims=/ " %%A In ('RoboCopy . $ testfiles*.* /L /NS /NJS /NJH /NDL /NC /TS')Do #Ren "%%E" "testfiles%%A%%B%%C%%~xE"
If each renamed file is run through the for loop again, you may need to expand this from a single line solution to prevent it.
In both code examples, the Delimiters are /TAB
I have a file by the name yyyymmddFile1.txt where date prefix is added in a particular format.
I need to copy that file from one location to another and I need to pick today's and yesterday's file
For today, I wrote
SET TODAY=%date:~10,4%%date:~4,2%%date:~7,2%
SET MAINPATH=D:\%TODAY%File1.txt
if exist %MAINPATH% (
COPY D:\%TODAY%File1.txt D:\NDM\InFileQueue\%TODAY%File1.txt
)
so, This will set the filename to 20190502File1.txt
But I can't figure out how to pass yesterday's date as a variable. I need to do something like this -
SET YESTERDAY= ??
SET MAINPATH=D:\%YESTERDAY%File1.txt
if exist %MAINPATH% (
COPY D:\%YESTERDAY%File1.txt D:\NDM\InFileQueue\%YESTERDAY%File1.txt
)
You can incorporate vbs and get a proper date format.Here you simply have to change the value of set day=-1 to toggle the number of days you want to remove from today's date.
#echo off
set day=-1
echo >"%temp%\%~n0.vbs" s=DateAdd("d",%day%,now) : d=weekday(s)
echo>>"%temp%\%~n0.vbs" WScript.Echo year(s)^& right(100+month(s),2)^& right(100+day(s),2)
for /f %%a in ('cscript /nologo "%temp%\%~n0.vbs"') do set "result=%%a"
del "%temp%\%~n0.vbs"
set "yyyy=%result:~0,4%"
set "mm=%result:~4,2%"
set "dd=%result:~6,2%"
set "final=%yyyy%%mm%%dd%"
echo Just doing an echo to screen of %final% for testing.
set "MAINPATH=D:\%final%File1.txt"
if exist %MAINPATH% (
copy D:\%final%File1.txt D:\NDM\InFileQueue\%final%File1.txt
)
To expand a little on my comment…
For files from both today and yesterday as a batch-file:
#Set "Src=D:\."
#Set "Dst=D:\NDM\InFileQueue"
#Set "Ext=.txt"
#RoboCopy "%Src%" "%Dst%" "*%Ext%" /MaxAge:2 > Nul
Or as a single command from either cmd.exe or a batch-file, (prepend the line with # to turn off its echoing if your wish):
RoboCopy "D:\." "D:\NDM\InFileQueue" "*.txt" /MaxAge:2 > Nul
For files from yesterday only, (ignoring todays), as a batch-file:
#Set "Src=D:\."
#Set "Dst=D:\NDM\InFileQueue"
#Set "Ext=.txt"
#RoboCopy "%Src%" "%Dst%" "*%Ext%" /MaxAge:2 /MinAge:1 > Nul
Or as a single command from either cmd.exe or a batch-file, (prepend the line with # to turn off its echoing if your wish):
RoboCopy "D:\." "D:\NDM\InFileQueue" "*.txt" /MaxAge:2 /MinAge:1 > Nul
You will note that there is one oddity, D:\., RoboCopy doesn't like the source or destination paths to end with a trailing backslash, so when one of them is the root of a drive, e.g. D:\, it is necessary to add the period, (you cannot use D:). Non root drive sources and destinations would simply use the path as I have in the example above for %Dst%.
Another way would be to use PowerShell. When you are satisfied that the files will be copied correctly, remove the -WhatIf switches.
=== get2files.ps1
$sourcedir = 'C:/the/original/directory'
$destinationdir = 'C:/the/new/directory'
$filetoday = (Join-Path -Path $sourcedir -ChildPath (Get-Date -Format yyyyMMdd)) + 'File1.txt'
$fileyesterday = (Join-Path -Path $sourcedir -ChildPath (Get-Date (Get-Date).AddDays(-1) -Format yyyyMMdd)) + 'File1.txt'
if (Test-Path -Path $filetoday) { Copy-Item -Path $filetoday -Destination 'C:/the/new/directory' -WhatIf }
if (Test-Path -Path $fileyesterday) { Copy-Item -Path $filetoday -Destination 'C:/the/new/directory' -WhatIf}
=== get2files.bat
powershell -NoLogo -NoProfile -File "%~dp0get2files.ps1"
I have a folder with more folders within folder.
I'm looking to make all files at a certain "level" be moved up one.
For example I have:
ParentFolder\Actor1\Movie\HighRes\HighresMovie.mp4
ParentFolder\Actor1\Movie\LowresMovie.mp4
ParentFolder\Actor2\Movie\HighRes\HighresMovie.mp4
ParentFolder\Actor2\Movie\LowresMovie.mp4
But I want it to look like:
ParentFolder\Actor1\Movie\HighresMovie.mp4
ParentFolder\Actor1\Movie\LowresMovie.mp4
ParentFolder\Actor2\Movie\HighresMovie.mp4
ParentFolder\Actor2\Movie\LowresMovie.mp4
This is a massive folder with about 1000 "Actor" folders.
I currently have this command line command partially working:
for /f "delims==" %i in ('dir /a:d /b') do for /f "delims==" %f in ('dir "%i" /a:d /b') do (move "%i\%f\*.*" "%i"&&rd "%i\%f" /s /q)
I can run this command from the command line within the "Actor" folder and it does exactly what I want. Now I want to be able to run it from the "ParentFolder" and have it apply the same command to every "Actor" folder I have.
this gets a list of files in the $TopDir tree that match *.mp4 AND have HighRes in the path name. it then iterates thru the list, gets the parent dir name, and moves the file to that parent dir.
remove the -WhatIf when you are ready to do it for real ... [grin]
$TopDir = "$env:TEMP\ParentFolder"
$Filter = '*.mp4'
$SourceDir = 'HighRes'
$MoveFileList = Get-ChildItem -LiteralPath $TopDir -Filter $Filter -Recurse -File |
Where-Object {$_.DirectoryName -match $SourceDir}
foreach ($MFL_Item in $MoveFileList)
{
$DestDir = Split-Path -Path $MFL_Item.DirectoryName -Parent
Move-Item -LiteralPath $MFL_Item.FullName -Destination $DestDir -WhatIf
}
output [reformatted to be easier to read] ...
What if: Performing the operation
"Move File"
on target
"Item: C:\Temp\ParentFolder\Actor1\Movie\HighRes\HighresMovie.mp4
Destination: C:\Temp\ParentFolder\Actor1\Movie\HighresMovie.mp4".
What if: Performing the operation
"Move File"
on target
"Item: C:\Temp\ParentFolder\Actor2\Movie\HighRes\HighresMovie.mp4
Destination: C:\Temp\ParentFolder\Actor2\Movie\HighresMovie.mp4".
I have a script which can list all files under a folder and its subforlders, with some properties such as path, file name, modified date and size. But, I can't add one extra property, file owner.
#ECHO off
SET v1=%%~dpF
SET v2=%%~nxF
SET v3=%%~zF
(for /r %%F in (*) do #echo "%v1%","%v2%",%v3%) > test.csv
PAUSE
Basically I want to add a 4th parameter, which should show file owner. It is in Windows 7 environment.
You can use the dir command with the /q switch to include the owner of each file.
#ECHO OFF
SetLocal EnableDelayedExpansion
for /r %%a in (*) do for /f "tokens=5" %%b in ('dir /q "%%~fxa" ^| findstr "%%~nxa"') do (
echo "%%~dpa","%%~nxa","%%~za","%%b"
) >> test.csv
This will always append to test.csv, if you want to always recreate test.csv you can encase your entire for loop in parenthesis (as you had);
#ECHO OFF
SetLocal EnableDelayedExpansion
(for /r %%a in (*) do for /f "tokens=5" %%b in ('dir /q "%%~fxa" ^| findstr "%%~nxa"') do (
echo "%%~dpa","%%~nxa","%%~za","%%b"
)) > test.csv
Not exactly what you asked for, but I adapted a PowerScript to show what you ask for. Just update the PARAM section with your file and folder names, copy and paste into PowerShell and hit enter twice:
PARAM (
$Path = 'C:\Users\PATHHERE\',
$report = 'C:\Users\USERNAME\Desktop\OUTPUTFILENAMEHERE.csv'
)
$LastWrite = #{
Name = 'Last Write Time'
Expression = { $_.LastWriteTime.ToString('u') }
}
$Owner = #{
Name = 'File Owner'
Expression = { (Get-Acl $_.FullName).Owner }
}
$HostName = #{
Name = 'Host Name'
Expression = { $env:COMPUTERNAME }
}
Get-ChildItem -Recurse -Path $Path |
select $HostName, $Owner, Name, Directory, $LastWrite, Length |
Export-Csv -NoTypeInformation $Report
This script adapted from info found here. I find batch files to be more and more trouble to deal with these days, and PowerShell is very flexible. The guys over at serverfault.com will no doubt be able to help you better with these kinds of questions.