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

#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 …

Related

How to move thousands of image files into subfolders each with 400 image files?

I have 2000 images and I want to move them into different folders. Each folder should contains 400 images and each folder is in a different path.
\Desktop\images contains:
0001.jpeg
0002.jpeg
...
2000.jpeg
The files should be moved to the folders:
\Desktop\Project\Folder1\images:
0001.jpeg
0002.jpeg
...
0400.jpeg
\Desktop\Project\Folder2\images
0401.jpeg
0402.jpeg
...
0800.jpeg
\Desktop\Project\Folder3\images:
1801.jpeg
1802.jpeg
...
1200.jpeg
\Desktop\Project\Folder4\images:
1201.jpeg
1202.jpeg
...
1600.jpeg
\Desktop\Project\Folder5\images:
1601.jpeg
1602.jpeg
...
2000.jpeg
Graphical display of the folders
Here is a commented batch file for this file moving task with some extras to make it interesting (for me):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "SourceFolder=%UserProfile%\Desktop\images"
if not exist "%SourceFolder%\*.jpeg" goto :EOF
set "DestinationPath=%UserProfile%\Desktop\Project"
set "DestinationName=Folder"
set "FolderNameLength=6"
set "MaxFileCount=400"
setlocal EnableDelayedExpansion
set "FolderNumber=0"
set "FileCount=%MaxFileCount%"
set "DestinationFolder=!DestinationPath!\!DestinationName!"
rem Search for all non-hidden subfolders with a name starting with the
rem destination folder name and having a number append and determine
rem the greatest folder number in all existing folder names. Folder
rem names with one or more leading zeros are not supported by this code.
for /F "delims=" %%I in ('dir "!DestinationFolder!*" /AD-H-L /B 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /R "^folder[0123456789][0123456789]*$"') do (
set "FolderName=%%I"
if !FolderName:~%FolderNameLength%! GTR !FolderNumber! set "FolderNumber=!FolderName:~%FolderNameLength%!"
)
rem Determine the number of *.jpeg files in the images folder in the folder
rem with greatest folder number if there is an existing images folder at all.
if exist "!DestinationFolder!!FolderNumber!\images\" (
set "FileCount=0"
for /F "eol=| delims=" %%I in ('dir "!DestinationFolder!!FolderNumber!\images\*.jpeg" /A-D /B 2^>nul') do set /A FileCount+=1
)
rem Get a list of JPEG files in source folder loaded into memory of the
rem Windows command processor ordered by name and move all these files
rem with making sure that no images folder has more than the number of
rem JPEG files as defined above. The code below is not capable moving
rem files with one or more exclamation marks because of always enabled
rem delayed expansion.
rem Note: The command DIR orders the file names strictly alphabetically
rem and not alphanumerical as done by Windows File Explorer. So
rem the JPEG file names should have all the same number of digits.
for /F "eol=| delims=" %%I in ('dir "!SourceFolder!\*.jpeg" /A-D /B /ON 2^>nul') do (
set /A FileCount+=1
if !FileCount! GTR %MaxFileCount% (
set "FileCount=1"
set /A FolderNumber+=1
md "!DestinationFolder!!FolderNumber!\images"
)
echo Moving file "%%I" to "!DestinationFolder!!FolderNumber!\images\"
move "!SourceFolder!\%%I" "!DestinationFolder!!FolderNumber!\images\"
if errorlevel 1 set /A FileCount-=1
)
endlocal
endlocal
This batch file works on no destination folder existing at all as well as some destination folders already existing in which case the number of JPEG files in destination folder with greatest number is found out to determine how much JPEG files to move additionally to the images folder of the FolderX with greatest number.
Please note that SourceFolder, DestinationPath, DestinationName, FolderNameLength and MaxFileCount must be adapted to local requirements.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
dir /?
echo /?
endlocal /?
findstr /?
goto /?
if /?
md /?
move /?
rem /?
set /?
setlocal /?
Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul and |. The redirection operators > and | must be escaped with caret character ^ on the FOR command lines to be interpreted as literal character swhen Windows command interpreter processes these command lines before executing command FOR which executes the embedded dir command lines without or with findstr with using a separate command process started in background with %ComSpec% /c and the command line within ' appended as additional arguments.
As you are using an Operating System which is equipped with powershell, here's an alternative which utilises that instead:
DistributeFiles.ps1
$DesktopPath = [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::Desktop)
$SourceDir = $DesktopPath + "\images"
$FileMask = "*.jpeg"
$DestDir = $DesktopPath + "\Project"
$FilesPerDir = 400
$DestStartNum = 1
$i = 0
Get-ChildItem -Path $SourceDir -Filter $FileMask -Name | Sort-Object | ForEach-Object {
New-Item -Path ($DestDir + "\Folder" + $DestStartNum) -Type Directory -Force > $Null
Move-Item ($SourceDir + "\" + $_) ($DestDir + "\Folder" + $DestStartNum)
$i++
If ($i -Eq $FilesPerDir) {
$DestStartNum++
$i = 0
}
}
In order to remain on topic with your cmd tag, you could run that script from a Command Prompt window like this:
%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy RemoteSigned -File "L:\ocation\Of\DistributeFiles.ps1"
Another way to do it would be to use the PowerShell that is already on your supported Windows system. This cmd .bat file script runs a PowerShell script that will use the first four (4) digits of the .jpeg file name to determine to which directory it should be moved. Files not beginning with four (4) digits will not be moved.
Put both the .bat and .ps1 file in the same directory. When you are satisfied that the correct directories will be created and the files will be moved to the correct directory, remove the -WhatIf from both the mkdir and Move-Item commands.
=== DistributeFiles.bat
#powershell -NoLogo -NoProfile -File "%~dp0%~n0.ps1"
=== DistributeFiles.ps1
$ProjectPath = Join-Path -Path $Env:USERPROFILE -ChildPath 'Desktop\Project';
$NFilesPerDirectory = 400;
Get-ChildItem -File -Path (Join-Path -Path $Env:USERPROFILE -ChildPath 'Desktop\images') -Filter '*.jpeg' |
ForEach-Object {
# Check to see if the filename starts with four (4) digits.;
if ($_.BaseName -match '^(\d{4}).*') {
$FolderNumber = [math]::Floor([int]$Matches[1] / $NFilesPerDirectory);
$FolderName = 'Folder' + $FolderNumber.ToString();
$FolderPath = Join-Path -Path $ProjectPath -ChildPath $FolderName;
# If the destination directory does not exist, create it.;
if (-not (Test-Path -Path $FolderPath)) { mkdir $FolderPath -WhatIf | Out-Null }
# Move the file to the destination directory.;
Move-Item -Path $_.FullName -Destination $FolderPath -WhatIf
}
}
If, for some reason, you cannot entertain the use of a .ps1 script file, this can be coded inside the .bat file script.
powershell -NoLogo -NoProfile -Command ^
$ProjectPath = Join-Path -Path $Env:USERPROFILE -ChildPath 'Desktop\Project'; ^
$NFilesPerDirectory = 400; ^
Get-ChildItem -File -Path (Join-Path -Path $Env:USERPROFILE -ChildPath 'Desktop\images') -Filter '*.jpeg' ^| ^
ForEach-Object { ^
^<# Check to see if the filename starts with four (4) digits.#^> ^
if ($_.BaseName -match '^^(\d{4}).*') { ^
$FolderNumber = [math]::Floor([int]$Matches[1] / $NFilesPerDirectory); ^
$FolderName = 'Folder' + $FolderNumber.ToString(); ^
$FolderPath = Join-Path -Path $ProjectPath -ChildPath $FolderName; ^
^<# If the destination directory does not exist, create it.#^> ^
if (-not (Test-Path -Path $FolderPath)) { mkdir $FolderPath -WhatIf ^| Out-Null }; ^
^<# Move the file to the destination directory.#^> ^
Move-Item -Path $_.FullName -Destination $FolderPath -WhatIf; ^
}; ^
};

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

xCopy into the top folder of a directory

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

cmd how to delete JPG file and keep only RAW

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

Batch Command Error

#echo off
setlocal
set Folder=C:\Test
set FileMask=*.txt
set OldestFile=
for /f "delims=" %%a in ('dir /b /o:d %Folder%\%FileMask%" 2^>NUL') do (
set OldestFile=%%a
goto Break
)
:Break
if "%OldestFile%"=="" (
echo No files found in '%Folder%' matching '%FileMask%'!
) else (
del "%Folder%\%OldestFile%"
)
Hi, I am trying to delete the oldest file in the Test directory using batch file but I am getting an error after running it with or without an Admin Privilege where 'dir /b /o:d "C\Test" 2>NUL' is not recognized as an internal or external command, operable program or batch file. I am trying to run it on Windows Server 2012 R2 x64 bit. Please help. Thank you.
PowerShell seems a bit more concise. Once you are satisfied that it is deleting the correct file, remove the -WhatIf switch.
C:\src\t>type xxx.bat
#ECHO OFF
SET "Folder=C:\src\t"
SET "FileMask=*.txt"
powershell -noprofile -command "dir %Folder% -filt %FileMask% -file |"^
"sort -p LastWriteTime -d |"^
"select -l 1 |"^
"del -WhatIf"
C:\src\t>xxx.bat
What if: Performing the operation "Remove File" on target "C:\src\t\th.txt".
If you are running PowerShell, the syntax is much cleaner.
PS C:\src\t> type .\xxx.ps1
$Folder = 'C:\src\t'
$FileMask = '*.txt'
Get-ChildItem -Path $Folder -Filter $FileMask -File |
Sort-Object -Property LastWriteTime -Descending |
Select-Object -Last 1 |
Remove-Item -WhatIf
PS C:\src\t> .\xxx.ps1
What if: Performing the operation "Remove File" on target "C:\src\t\th.txt".

Resources