I'd like to find all the folders under a specific path (C:\main_folder) that have no files in it.
I've found a way with cmd for doing it:
#echo off
setlocal
set "folder=C:\main_folder"
for /r "%folder%" /d %%F in (.) do dir /b "%%F" | findstr "^" >nul || (echo %%~fF) > "C:\empty_folders_list.txt"
but if I have
C:\main_folder\folder_1 containing folder_2 and no files and
C:\main_folder\folder_1\folder_2 with no files, that code gives only
C:\main_folder\folder_1\folder_2, while I'd like to have also
C:\main_folder\folder_1 in it.
It shouldn't look only to the folders that have no files, cause I can have
C:\main_folder\folder_3 containing folder_4 and no files but if
C:\main_folder\folder_3\folder_4 contains file, folder_3 and folder_4 shouldn't be listed.
And after having the list I want to delete them (the list is only for checking/saving them).
How do I write it?
Thanks!
This worked for me:
#echo off
setlocal
set "folder=C:\temp\bob"
for /r "%folder%" /d %%F in (.) do dir /b /s /a-d "%%F" 2>nul | findstr "^" >nul || echo %%~fF
output:
C:\temp>test
C:\temp\bob\empty parent
C:\temp\bob\empty parent\empty subfolder
C:\temp\bob\not empty parent\empty subfolder
If you are a supported Windows system, it will have PowerShell. This requires PowerShell 3.0+, but can be done with 2.0 with some modifications.
This gathers the list of subdirectories and sorts the names descending. This is so that an empty directory that had empty subdirectories will be removed.
When you are satisfied that the correct directories will be removed, remove the -WhatIf from the Remove-Item command.
=== Remove-Empties.ps1
$baseDir = 'C:\main_folder'
$dirs = (Get-ChildItem -Directory -Recurse -Path $baseDir).FullName | Sort-Object -Descending
foreach ($dir in $dirs) {
if (((Get-ChildItem -Directory -Path $dir).Length -eq 0) -and
((Get-ChildItem -File -Path $dir | Measure-Object).Count -eq 0)) {
"Removing directory $($dir)"
Remove-Item -Path $dir -WhatIf
}
}
=== Invoke from cmd.exe command line or .bat file script
powershell -NoLogo -NoProfile -File ".\Remove-Empties.ps1" >"C:\empty_folders_list.txt"
Related
I have a series of image files with a set prefix that I would like to remove. Example of the filenames that I will have:
Image_2022-06-09-12-29-00_Filename-01
Image_2022-07-09-13-29-59_Filename-02
Image_2022-02-11-09-26-31_Filename-03
I would like them to turn into:
Filename-01
Filename-02
Filename-03
I currently have a .bat file that manages to remove the first part of all the files which can either be .jpg or .png files:
set current_dir=%cd%
powershell -Command "get-childitem *.png | rename-item -newname { [string]($_.name).substring(26) }"
powershell -Command "get-childitem *.jpg | rename-item -newname { [string]($_.name).substring(26) }"
My problem now however, is that once I run this and the files are renamed, I cannot copy in new files and run the .bat file again because it will rename the files that have already been renamed. Is it possible to identify a sequence of the first part of a filename, and then apply this only to those files? The first 26 characters will always be in that format, but the numbers may change.
This simple pure Batch file should do the work (and should run much faster than the PS versions):
#echo off
for /F "delims=" %%a in ('dir /B *.png *.jpg') do for /F "tokens=3 delims=_" %%f in ("%%a") do ren %%a %%f
EDIT 2022/06/22: New method to fulfill the new specifications
#echo off
for /F "delims=" %%a in ('dir /B *.png *.jpg') do for /F "tokens=2* delims=_" %%e in ("%%a") do ren %%a %%f
Seems to me all you have to do is to split the file's BaseName (name without extension) on the underscore and take the last element. Then recombine that with the file's extension and you're good to go.
(Get-ChildItem -Path 'X:\WhereTheFilesAre' -File | Where-Object { $_.Extension -match '\.(jpg|png)' }) |
Rename-Item -NewName {'{0}{1}' -f ($_.BaseName -split '_')[-1], $_.Extension }
As per your comment, the filenames could have mixed hyphens and underscores, you can change the Rename-Item scriptblock into
Rename-Item -NewName {'{0}{1}' -f ($_.BaseName -replace '.*[-_](\w+[-_]\d+)$', '$1'), $_.Extension }
Tests:
'Image_2022-06-09-12-29-00_Filename-01' -replace '.*[-_](\w+[-_]\d+)$', '$1' # --> Filename-01
'Image_2022-07-09-13-29-59_Filename_02' -replace '.*[-_](\w+[-_]\d+)$', '$1' # --> Filename_02
As for setting the PowerShell function to use the same current directory as your batch file, please read this answer
I have a directory with files directly in it C:\test1.
I want to copy all these files to C:\test2 only if the file does not exist in any subdirectory in C:\test2.
Need to write a Windows batch file which can do this. Any help is appreciated.
I have tried using the following, but it does not searches recursively in destination directory:
For %%F In ("C:\test1*") Do If Not Exist "C:\test2\%%~nxF" Copy "%%F" "C:\test2\%%~nxF"
If you wanted to push ahead into PowerShell, this code might help. When you are satisfied the the files will be copied correctly, remove the -WhatIf from the Copy-Item cmdlet.
Ok, I admit that I do not have a test1 and test2 directory for testing, but this will probably get you started.
$targetdir = 'C:\test2'
Get-ChildItem -File -Path 'C:\test1' |
ForEach-Object {
if ((Get-ChildItem -File -Recurse -Path $targetdir -Filter $_.Name).Count -eq 0) {
Copy-Item -Path $_.FullName -Destination $targetdir -WhatIf
}
}
If you save the script above as Copy-IfNone.ps1, then you can run it from a cmd shell using:
powershell -NoProfile -File .\Copy-IfNone.ps1
Examples make it easier for everyone to understand the requirements for a task.
So let me start with an example.
Source directory C:\test1 contains following files:
Test1.txt
Test2.txt
Test3.txt
Destination directory tree C:\test2 contains following directories and files:
Subfolder1
Test2.txt
Subfolder2
Subfolder3
Test3.txt
For this example just file Test1.txt should be copied to directory C:\test2 because Test2.txt and Test3.txt exist already in subfolders of C:\test2.
So the directory tree C:\test2 should look as follows after batch file execution:
Subfolder1
Test2.txt
Subfolder2
Subfolder3
Test3.txt
Test1.txt
This can be achieved with:
#echo off
for %%I in ("C:\test1\*") do (
dir "C:\test2\%%~nxI" /A-D /B /S >nul 2>nul
if errorlevel 1 copy "%%I" "C:\test2\" >nul
)
It is also possible to do that with a single command line:
#for %%I in ("C:\test1\*") do #dir "C:\test2\%%~nxI" /A-D /B /S >nul 2>nul || copy "%%I" "C:\test2\" >nul
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 /?
copy /?
echo /?
for /?
if /?
I want to delete with a batch for windows all files with extension *.jpg in a folder (test) and its subfolder, except two files ex: abc.jpg and xyz.jpg that occur several times in different folders.
I tried with
h:
cd test
for /R %%f in (*.jpg) do (if not "%%~xf"=="abc.jpg" if not "%%~xf"=="'xyz.jpg" del "%%~f")
but I failed.
Anyone can help me? Thank you
You might try a FOR loop and check to see if the file name is one that should not be deleted. When you are confident that the correct files would be deleted, remove the echo from the DEL command.
FOR /F "delims=" %%f IN ('DIR /S /B "C:\src\t\*.jpg"') DO (
IF NOT "%%~nf" == "abc" IF NOT "%%~nf" == "xyz" (
echo DEL "%%~f"
)
)
This can also be done in a .bat file script using Powershell. When you are confident that the correct files would be deleted, remove the -WhatIf from the Remove-Item cmdlet.
powershell -NoProfile -Command ^
"Get-ChildItem -Recurse -Filter '*.jpg' -exclude 'abc.*','xyz.*' |" ^
"ForEach-Object { Remove-Item -Path $_ -WhatIf }"
I would like to delete all the files located in folders named \log\ . This folder can be everywhere (at any levels) in sub directories
ideally i want to do something like
del c:\myapp\*\log\* /s /q
how can i do this ?
A single line example from the Command Line, cmd.exe:
For /F "Delims=" %A In ('Dir /B/S/AD "C:\myapp\log" 2^>Nul') Do #Del /A/F/S/Q "%A\*"
If you want it inside a batch file, *.cmd|*.bat:
#For /F "Delims=" %%A In ('Dir /B/S/AD "C:\myapp\log" 2^>Nul') Do #Del /A/F/S/Q "%%A\*"
Here is a command that can be used in a .bat file script. When you are confident that the correct files will be deleted, remove the -WhatIf from the Remove-Item cmdlet.
powershell -NoProfile -Command ^
"Get-ChildItem -Directory -Recurse -Filter 'log' | " ^
"ForEach-Object { Get-ChildItem -File -Path $_.PSPath | Remove-Item -WhatIf }"
Yes, it can be sorter and more cryptic and more expensive to maintain. Almost as much fun as a .bat FOR loop.
powershell -NoProfile -Command "gci -di -rec -filt 't' | %% { gci -file $_.PSPath | ri -WhatIf }"
I need to rename various files in different folders. There is a prefix 'f_' in all the filenames that need to be removed.
I managed to do this using the following lines in Powershell.
cd "C:\Users\pieter\Desktop\Folder1\Folder2\20140402_Export"
Get -ChildItem -filter "*f_*" -recurse | Rename-item -newname { $_.name -replace "f_","" }
This works, but how do I make a .bat out of this?
I would like to doubleclick a script file that automatically does the same job.
Thanks!
Create a batch file and the following there, it will execute your command in Powershell thread and exit.
#powershell "cd 'C:\Users\pieter\Desktop\Folder1\Folder2\20140402_Export'; Get-ChildItem -filter "*f_" -recurse | Rename-item -newname { $_.name -replace 'f_','' }"
try this:
#cd /d "C:\Users\pieter\Desktop\Folder1\Folder2\20140402_Export"
for /f "delims=" %%a in ('dir /b /a-d /s "*f_*"') do (
set "name=%%~na"
setlocal enabledelayedexpansion
set "new=!name:f_=!"
ren "%%a" "!new!%%~xa"
endlocal
)