Batch: move files group without set source/target folder - windows

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
}

Related

Batch rename files and organize them Bat Script

Friends, I need to rename pdf files to a certain standard. For that I made the following script:
c:
cd \importation
if not exist %1 goto end
md %~n1
move %1 %~n1\P%~n1_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
if not exist %2 goto end
md %~n2
move %2 %~n2\P%~n2_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
if not exist %3 goto end
md %~n3
move %3 %~n3\P%~n3_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
if not exist %4 goto end
md %~n4
move %4 %~n4\P%~n4_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
if not exist %5 goto end
md %~n5
move %5 %~n5\P%~n5_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
if not exist %6 goto end
md %~n6
move %6 %~n6\P%~n6_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
if not exist %7 goto end
md %~n7
move %7 %~n7\P%~n7_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
if not exist %8 goto end
md %~n8
move %8 %~n8\P%~n8_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
if not exist %9 goto end
md %~n9
move %9 %~n9\P%~n9_V1_A0V0_T07-54-369-664_S00001_Volume.pdf
:end
It turns out that the script only modifies up to 9 files at a time. Does anyone know how I can make this change to all files in the folder? Sometimes there are 100,200 or even more pdfs
Use Get-ChildItem to discover the files, then inspect their BaseName property to get the file name without the extension:
$rootFolder = 'C:\importation'
Get-ChildItem $rootFolder -File -Filter *.pdf |ForEach-Object {
# create new folder
$newFolder = mkdir -Path $rootFolder -Name $_.BaseName
# construct target path
$targetPath = Join-Path $newFolder.FullName "P$($_.BaseName)_V1_A0V0_T07-54-369-664_S00001_Volume.pdf"
# move file
$_ |Move-Item -Destination $targetPath
}
This should work
# Define variables
$Folder = "C:\myfolder"
$OldFileName = "OldFileName1.pdf"
$NewFileName = "NewFileName1.pdf"
# Get all files in the folder non-recursively
$Files = Get-ChildItem $Folder
# For each file
foreach ($File in $Files){
# If file matches the OldFileName
If ($File.Name -eq $OldFileName){
# Rename the file to the new name
Rename-Item -Path $File.FullName -NewName $NewFileName
}
}

store yesterdays date in yyyymmdd format into a variable

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"

How can I execute a command in each subdirectory of a folder?

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".

Windows batch script - Regular expression for file names

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

Need a Batch file copy all txt files to a sub folder, but rename if it already exists

Ok,
I have multiple text files that will be coming into a folder that I am processing into a single output file. The batch will run every few hours.
for %%f in (*.txt) do type "%%f" >> ESOComplete\ESOInput.txt
This will copy all text from text files to one single text file in another subfolder.
From there I need one to move all files (Example 510002.txt) to a subfolder called ESOMoved. Leaving the root folder empty so next time the batch runs it doesn't add the same data to the ESOInput.txt
Now, I need the batch file that moves the orignal data from the root to not overwrite, so if files already exists I want it to rename it (From 510002.txt to 5100022.txt)
In the end it should be
1. Move all text from all .txt documents to one output file. (Which is already done)
2. Move all .txt documents to subfolder called ESOMoved, unless that specific document already exists, in which case rename, and then move.
EDIT
If the file with the appended 2 already exists the number is increased until it is free.
#Echo off
:: Start in base folder
PushD "Q:\Test\2017\07\22"
for %%f in (??????.txt) do (
type "%%f" >> "ESOComplete\ESOInput.txt"
If Not Exist "ESOMoved\%%f" (
Move "%%f" "ESOMoved\"
) Else (
Set Num=2
Call :Move "%%f"
)
)
PopD
Goto :Eof
:Move
Set "NewName=ESOMoved\%~n1%Num%%~x1"
If Not Exist "%NewName%" (
Echo Move %1 "%NewName%"
Move %1 "%NewName%" >Nul 2>&1
Exit /B 0
)
Set /A Num+=1
Goto :Move
The trick to this is devising a renaming scheme. The code below appends "-N" to the file basename to create a unique file it will keep incrementing N until if finds a filename that does not exist.
Save this file as esomover.ps1.
$files = Get-ChildItem -Path 'C:/src/t/ESO/' -File -Filter 'file*.txt'
$sum_file = 'C:/src/t/ESO/ESOComplete/ESOInput.txt'
$arch_dir = 'C:/src/t/ESO/ESOArchive'
if (-not (Test-Path -Path $sum_file)) { New-Item -Path $sum_file -ItemType File }
foreach ($file in $files) {
Add-Content -Path $sum_file -Value (Get-Content $file.FullName) -Encoding Ascii
if (-not (Test-Path "$($arch_dir)/$($file.Name)")) {
Move-item $file.FullName $arch_dir
} else {
$i = 0
$nfn = ''
do {
$nfn = "$($file.BaseName)-$($i.ToString()).txt"
$i++
} while (Test-Path -Path "$($arch_dir)/$($nfn)")
Move-Item $file.FullName "$($arch_dir)/$($nfn)"
}
}
Run this script from a cmd.exe shell or .bat file using:
powershell -noprofile -file .\esomover.ps1

Resources