So i'm currently trying to delete a bunch of subfolders that were created by a program, on a recurring basis because it will recreate the subfolders. I know how to schedule the batch file, right now my issue is how to efficiently create the batch file to begin with. To clarify, say i have a directory named D:\IGSG. There are 250 folders within D:\IGSG, and within each one of those is a folder named D:\IGSG\F252341\arg. I want to delete all of the \arg folders, from all ~250 F folders I have, without deleting the other files inside the F folders. Right now the only way to do it that I know of would be to have a batch that goes
cd D:\IGSG\F252341
del /Q arg
and to repeat those lines for every subfolder, but typing out those folder names for every folder in there would be tedious, especially considering new ones are created from time to time. So i'm looking for a way with a batch to delete the subfolder of a subfolder, without deleting other files, if that makes sense.
On the cmd line for /d /r X:\path in combination with a wildcard will enumerate all folders names arg the appended .? meets this requirement:
for /d /r D:\IGSG %A in (arg.?) do #echo rd /s /q "%A"
if the output looks right remove the echo.
In a batch file double the %-signs -> %%A
#Echo off
for /d /r D:\IGSG %%A in (arg.?) do echo rd /s /q "%%A"
One of the rare cases where batch/cmd line can compete with PowerShell.
This PowerShell script will recurse through the subdirectory structure and delete all files and subdirectories inside arg directories. Be sure to change the location of the IGSG directory to yours. When you are satisfied that the correct files will be deleted, remove the -WhatIf from the Remove-Item cmdlet.
Get-ChildItem -Directory -Recurse -Path 'C:\src\t\delsubs\IGSG\F*' -Filter 'arg' |
Remove-Item -Path {(Join-Path -Path $_.FullName -ChildPath '*')} -Recurse -Force -WhatIf
If you need to run it from a cmd.exe shell, put the code above into a file named 'dodel.ps1' and run using:
powershell -NoProfile -File .\dodel.ps1
Related
I would like to write a script that searches through a folder and deletes any raw files (.nef) that don't have a matching jpg. For example,
Folder structure:
DSC_0001.nef
DSC_0001.jpg
DSC_0002.nef
DSC_0003.nef
The program would delete DSC_0002.nef and DSC_0003.nef.
How can I do this?
FOR /R %%F IN (*.NEF) DO #IF NOT EXIST "%%~dpnF.jpg" DEL "%%F"
Note: the /R switch means recursive (i.e. it will continue to run this command throughout the entire directory tree from the directory where it is run from). Omit that switch if you don't want to process subdirectories as well.
A possible PowerShell solution:
Get-ChildItem -Path "C:\temp\nef" -Filter "*.nef" | foreach {
if( -not (Get-Item $_.FullName.Replace('.nef','.jpg') -ErrorAction SilentlyContinue)){
$_ | Remove-Item -WhatIf
}
}
Remove the -WhatIf to actually make it delete the files.
You will need to use (for a single folder):
#echo off
cd to\folder
for %%A IN (*.nef) do (
if not exist %%~nA.jpg (del %%~fA)
)
And for multiple folders, use:
#echo off
for /R "full_path_to_parent_folder" %%A IN (*.nef) do (
if not exist %%~dpnA.jpg (del %%~fA)
)
Dear StackOverflow community,
Could you please advise me with a Batch code for the following scenario:
To find the folders named "Autoname" if they exist, and delete their
host folders (X), folder itself (Autoname) and all the files inside.
(X ) folders may have any names
The path is: %userprofile%\AppData\Local\ -X- \ "Autoname" \
folders & files.
I found similar post and similar post but it's not what I need.
Thank you All for your time, I especially appreciate the answer from #Compo, it is accepted as the best!
Your question now suggests that the Autoname directories exist any level within your temporary directory.
The following examples should be all that's required:
From a batch file:
#Echo Off
For /F "Delims=" %%A In ('"Dir/B/S/AD-L "%Temp%"|FindStr/IEC:"\\AutoName""'
) Do If Exist "%%~dpA" RD/S/Q "%%~dpA"
From the Command prompt:
#For /F "Delims=" %A In ('"Dir/B/S/AD-L "%Temp%"|FindStr/IEC:"\\AutoName""') Do #If Exist "%~dpA" RD/S/Q "%~dpA"
for /f "delims=" %i in ('dir /b /s /ad u:\sourcedir\*') do #if /i "%~nxi"=="e9" ECHO rd /s/q "%~dpi."
This should delete the parent of any subdirectory of the u:\sourcedir directory which itself contains a subdirectory e9. The directory names aren't magic - just what I used for testing.
Removal of the parent directory will delete all files and directories under the deleted directory.
This code will simply REPORT what it intends to do. Once verified you will need to remove the echo keyword to perform the deletion. Note that it's possible for this script line (it's intended to be invoked directly from the prompt) to generate error messages should it attempt to delete an e9 directory that existed below a directory its already deleted. Appending 2>nul to the line (including the leading space) should suppress reporting of such errors.
If you would like to move ahead into PowerShell, the following might work. When you are confident that the correct directories will be deleted, remove the -WhatIf from the Remove-Item cmdlet.
Get-ChildItem -Recurse -Directory -Filter 'Autoname' |
ForEach-Object { Remove-Item -Path $_.PSParentPath -Recurse -WhatIf }
I'm trying to move all .txt files in different folders to a single folder using a batch file, I'm new to batch coding so I'm having some difficulties.
My code is as follows:
FOR /D /r %%G IN ("C:\Users\Rodrigo\Desktop\PR\2016\08.2016\") DO MOVE G\*.txt C:\Users\Rodrigo\Desktop\PR\2016\
See the correct syntax of For /r or in an open cmd window type help for
#Echo off
For /r "C:\Users\Rodrigo\Desktop\PR\2016\08.2016\" %%G IN (*.txt
) Do echo Move "%%G" "C:\Users\Rodrigo\Desktop\PR\2016\"
Pause
If the output to screen looks OK remove the echo in front of the move command.
You could do this all in PowerShell. I am not sure it will work if you do not pass the $_.FullName which contains the path to the file.
Get-ChildItem -Path "C:\Users\Rodrigo\Desktop\PR\2016\08.2016\" -Filter *.txt | `
ForEach-Object { $_.FullName } | `
Move-Item -Destination "C:\Users\Rodrigo\Desktop\PR\2016\"
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
Here is some code I made :)
#echo off
set source="R:\Contracts\"
set destination="R:\Contracts\Sites\"
ROBOCOPY %source% %destination% *.srt *.pdf *.mp4 *.jpg /COPYALL /R:0 /S
for /r %source in (*) do #copy "%destination" .
R:\Contracts\ is full of folders which have files in them.
I want to copy all to R:\Contracts\Sites\ and flatten the folder structure.
Everything copies well but also the folder structure.
Thank you
You could do that with a PowerShell one liner.
In this example I filter out all the files with the .txt extension from all the subfolders. And then send them to the Copy-Item Cmdlet.
Combine the Cmdlets Get-Childitem (GCI for short), -recurse, and -filter and then pipe the result to the Copy-Item Cmdlet. Use -WhatIf first to check that the output is what you expected.
Copy to another folder (Use -WhatIf and verify the output to check your command before committing to copying the files):
Get-Childitem -recurse R:\Contracts -filter *.txt | Copy-Item -Destination R:\Contracts\Sites -WhatIf
To do multiple filetypes as you've asked, you can just run multiple commands, one for each filetype.
No single command will flatten the hierarchy for you; you will have to use multiple commands. It can be done simply by using FOR /R to walk the hierarchy, coupled with your copy/move command of choice (move, copy, xcopy, robocopy). Because your destination is within the source hierarchy, you need an IF to prevent the destination from being a source.
Before proceeding you should stop and think about what happens if the same file name appears in multiple source folders. You can only have one version in your destination folder. Can you guarantee no duplicate names exist? If not, which file should be kept? How can you structure the command to keep the file you want? This complication is probably why no command was ever written to simply flatten a hierarchy.
Here is your ROBOCOPY command integrated with the FOR /R solution.
#echo off
set source="R:\Contracts"
set destination="R:\Contracts\Sites"
::Not sure if this is needed
::It guarantees you have a canonical path (standard form)
for %%F in (%destination%) do set destination="%%~fF"
for /r %source% %%F in (.) do if "%%~fF" neq %destination% ROBOCOPY "%%F" %destination% *.srt *.pdf *.mp4 *.jpg /COPYALL /R:0
Similar to the previous Powershell option, I did the following to flatten a multi-subdirectory music folder:
#Get all files and not the directories
$files = Get-ChildItem -Path R:\Contracts -Recurse | Where {$_.PSIsContainer -eq $false}
#Copy items from sources to new destination
foreach ($file in $files){
Copy-Item -Path $file.FullName -Destination R:\Contracts\Sites\$($file.Name)
}
The Get-ChildItem with the -Recurse switch will get a listing of all sub-folders and files. The Where function is stripping out any directories by checking the boolean PSIsContainer property. Without stripping the directories the sub-folder structure would be created without files in them. This listing is stored in the $files variable.
The foreach function runs through the list of files in the $files variable and stores one item at a time in the $file variable. The Copy-Item function then uses the full path from $file.FullName and then copies the file to the destination with the same name from $file.Name.
I recently had to tackle this problem, and many files that I wanted to move to from the hierarchy to a single folder had the same name as each other, and I wanted to still flatten the hierarchy without them to being over-written.
What I did was write a script that moves the file, but renames it with the old hierarchy path in the name
for example:
source files:
C:\files\somefiles\file.txt
C:\files\otherfiles\file.txt
destination is C:\newdir\
files are created as
C:\newdir\somefiles-file.txt
C:\newdir\otherfiles-file.txt
here is the code, batch file 1 goes thru the files, batch file 2 renames and moves them (could also copy instead, if you want to preserve the source:
#echo off
for /r %%f in (*.*pr) do #renameandmovefilespart2.bat "%%f" "%%~ff" "%%~xf"
renameandmovefilespart2.bat
#echo off
Setlocal EnableDelayedExpansion
rem set the whole file path
set origWhole=%1
set origPathOnly=%2
set extension=%3
rem here you can set where the directory to hold the flattened hierarchy is
set destDir=c:\destinationDir\
rem set the directory to do a string replace
rem make this the starting directory, that you dont want in the newly renamed files
set startingDir=C:\starting\directory\
set nothing=
set slash=\
rem here you can set what the character to represent the directory indicator \ in the new files
set reaplcementDirectoryCharacter=--
set quote="
rem cut out the starting part of the directory
call set newname=%%origWhole:!startingDir!=!nothing!%%
rem replace slashes with new character
call set newname=%%newname:!slash!=!reaplcementDirectoryCharacter!%%
rem remove quotes
call set newname=%%newname:!quote!=!nothing!%%
rem #echo shortened: %newname%
rem #echo source path: %origPathOnly% newPath: %startingDir%
rem #echo extension: %extension%
rem rename the files
ren %origWhole% %newname%
rem prepare to move the file, clean up the source path
call set origPathOnly=%%origPathOnly:!quote!=!nothing!%%
move "%origPathOnly%%newname%" "%destDir%"
There's an old PCMag utility called Sweep.exe that can operate the same command in the current and subdirectory. I wouldn't put the destination as a subdirectory of the source directory. Put the destination elsewhere.
http://www.rarewares.org/files/case/Sweep.zip
cd c:\contracts
sweep copy *.* c:\sites
This will copy everything from c:\contracts and underneath to c:\sites
I use a similar command to flatten the hierarchy of a directory.
Take care with duplicates and how you want to handle them. Do you want to overwrite or handle a different way.
For those familiar with R copying files to a single folder could be easily scripted as follow. It is more efficient than ROBOCOPY for large sets and directory structures.
## R script - Flatten files in folder structure
# declare your paths
sourcepath<-C:\\Myfolder\\PicturesInStructure"
destpath<-"C:\\Myfolder\\PicturesTogether\\"
# read source filenames with path to vector variable
fileslist<-list.files(sourcepath,
pattern="*.jpg", # in this example copies JPG pictures
full.names=TRUE, # retrieves full path
recursive=TRUE, # runs through all subdirs
include.dirs=FALSE) # skips dir names (no to be copied)
# here you will get a head of your list
head(fileslist)
# ordinary loop by source filenames
for (i in 1:length(fileslist)) {
# Number of Slashes required to extract filename from the source path
NoS<-lengths(regmatches(fileslist[i], gregexpr("/", fileslist[i])))
# for lengthy processes it is good to know where you are with this
cat(i,fileslist[i]," \r")
# copy one file to a destination folder (full path composed with paste0())
file.copy(fileslist[i],paste0(destpath,unlist(strsplit(fileslist[i],"/"))[NoS+1]))
}