Moving specific extension up one directory level - windows

My current folder structure goes as follows:
E:\Videos\Movies\Random Folder Name\Subs\Random File Name.srt
I would like to move my .srt files up one level so it reads:
E:\Videos\Movies\Random Folder Name\Random File Name.srt
I would prefer this to be a .bat file, but am willing to use PowerShell.
~EDIT~
I found something online that partially works and edited it to my needs:
#echo off
set thisdir=%cd%
for /f "delims=" %%A in ('dir /b /ad') do (
cd /d "%%~dpnA"
for /f "delims=" %%B in ('dir /b /ad') do (
echo Level 2 Directory: %%~dpnB
cd /d "%%~dpnB"
for /f "delims=" %%C in ('dir /b /ad') do (
echo Level 3 Directory: %%~dpnC
cd /d "%%~dpnC"
move *.srt ..\
cd..
rd "%%~dpnC"
)
)
)
This works, but only for the first folder, I can't seem to make Level 2 recursive as that is the level with random movie names. I tried replace for /f with for /r, but it was a no go.

Here's a one-liner:
forfiles /m *.srt /s /c "cmd /c move #file .."

Full code (you can run this from any drive now):
#echo off
cd /d E:\Videos\Movies\
for /r %%i in (*.srt) do move "%%~dpnxi" "%%~dpi.."
pause
This looks for all files with type .srt and moves them to the folder it was found in -1 directory (%%~dpi is the directory it was found in, adding .. to a path removes the last directory, so C:\Users\.. would put you at C:\).
PS: This time I have tested this, and it works.

Although the answers already given work, I still wanted to try and figure out how to perfect the code to my exact needs. Couldn't accomplish this with CMD, so I looked into powershell (which was easier for me to grasp for some reason) and coded this:
$sourcefolder = "F:\Videos\Movies\*\Subs\"
$files = Get-ChildItem -Recurse $sourcefolder | where {$_.PSIScontainer -eq $false}
foreach ($file in $files)
{
$destinationFolder = Split-Path -Parent $file.Directory.FullName
move-item $file.FullName $destinationFolder
}
It doesn't specify .srt files, but they are the only extension located in that folder. Thank you for the help guys!

Related

Move directory contents based off findstr

Using windows 10 and I would like to recursively go through my movies folder and move any movies that have the genre Documentary written in it's associated nfo file. My directory structure is:
D:\Movie1
-Movie1.ext
-Movie.nfo
-Extrafanart\
D:\Movie2
-Movie2.ext
-Movie.nfo
-Extrafanart\
So, I want to search "movie.nfo" that will be located within each directory. If it has documentary genre, then I want to move that entire directory to a new location. The following I was able to get to work, but I'm only able to move the nfo file, not the directories' contents. I've been trying to work it out, but I can't figure it out:
for /F "tokens=*" %%I in ('findstr /i /s /m "<genre>Documentary</genre>" "D:\*.nfo"') do move "%%I" "E:\Documentaries\"
-EDIT-
So I have attempted to use powershell and I'm able to achieve the same thing, only moving the nfo, still can't move nfo's directory and contents:
get-childitem F:\Downloads\Movies\ -filter Movie.nfo -recurse | select-string -list -pattern "<genre>Documentary</genre>" | move -dest E:\Documentaries\
Here's my version of the solution:
# ECHO off
PUSHD %~dp0
CLS
CD Movies
FOR /D /r %%G IN ("*") DO (
findstr /C:"<genre>Documentary</genre>" "%%~G\*.nfo" >nul && (
ECHO "%%~G" is a Documentary!
MOVE "%%~G" C:\Documentaries
) || (
ECHO "%%~G" is NOT a Documentary!
)
)
CD ..
POPD
You may suppress the output of MOVE command as well like this:
MOVE "%%~G" C:\Documentaries >nul

cmd or powershell to get all subdirectories

I'm trying to figure out what cmd or powershell command I can use to get the subdirectories contained in a directory. I only want the last subdirectory in each listed, oo for example if I have something like:
matthew\folder1\folder2\folder3
and
matthew\folder6\folder7\folder8
and I am in the "matthew" directory, I just want to return the list that has:
folder1\folder2\folder3
folder6\folder7\folder8
I try to use dir /b /s but it gives me something like:
folder1
folder1\folder2
folder1\folder2\folder3
folder6
.
.
.
Any help would be greatly appreciated.
Still having difficulty understanding what you're looking for.
You want a list of all folders below the current folder which do not have any child folders. Additionally, you only want to display the portion of the path which is not specified by the current path.
For a Powershell answer:
Get-ChildItem -Directory -Recurse | Where-Object {
(Get-ChildItem $_.FullName -Directory).Count -eq 0;
} | ForEach-Object {
Write-Output $_.FullName.SubString((Get-Location).Path.Length);
}
Note the -Directory switch requires Powershell 3.0, if I remember right.
edited to reduce processing time
#echo off
setlocal enableextensions disabledelayedexpansion
subst :: .
for /r "::\" %%a in (.) do (
set "leaf=1"
for /d %%b in ("%%~fa\*") do if defined leaf set "leaf="
if defined leaf for /f "tokens=* delims=:\" %%b in ("%%~fa") do echo %%b
)
subst :: /d
There are two problems: determine what folders to show and remove the prefix from the output.
To solve the first problem, the folder structure under the current folder is enumerated and for each folder found it is tested if there is a folder inside. In there are no child folders, the current folder needs to be echoed.
To solve the second problem, all the operations are done under a subst drive. The current folder is defined as the root of the :: drive. That way, the full path to the current folder is removed from the string to output, replaced by a simple ::\, that will be removed with a properly configured for /f command when the folder must be echoed.
#ECHO OFF
SETLOCAL
:: Display leaves-only
SET "sourcedir=U:\sourcedir"
FOR /r "%sourcedir%" /d %%a IN (*) DO (
SET "flag=Y"
FOR /d %%b IN ("%%a\*") DO SET "flag="
IF DEFINED flag ECHO %%a
)
)
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
This worked for me.

Need to change Uppercase to lowercase using batch file

Right now I can use this with some success but I cant get it to work recursively? Any help would be awesome! I have been googling all day to find a solution and I havent found anything else that works.
for /f "Tokens=*" %%f in ('dir /l/b/a-d') do (rename "%%f" "%%f")
it has been suggested to do this but I've had no success.
for /f "Tokens=*" %%f in ('dir /l/b/a-d/s') do (rename "%%f" "%%f")
The rename command only takes a file name as the second parameter.
C:\>rename /?
Renames a file or files.
RENAME [drive:][path]filename1 filename2.
REN [drive:][path]filename1 filename2.
Note that you cannot specify a new drive or path for your destination file.
Here are the corrected rename parameters
for /f "tokens=*" %%F in ('dir /l/b/a-d/s') do rename "%%~fF" "%%~nxF"
Open a Command Prompt.
Go to the folder with the cd command (eg.: cd "path of your folder").
Open a powershell by typing: powershell.
Then input this:
get-childitem -recurse | Where {-Not $_.PSIsContainer} | Rename-Item -NewName {$_.FullName.ToLower()}

Windows scripting for loop

I'm new to Windows scripting. I wrote a small batch file to move subdirectories and files around in a large directory.
#ECHO OFF
for /f %x in ('dir /ad /b') do move %xipad %x\
for /f %x in ('dir /ad /b') do md %x\thumbs
for /f %x in ('dir /ad /b') do move %x\*thumb.png %x\thumbs\
for /f %x in ('dir /ad /b') do move %x\*thumb.jpg %x\thumbs\
for /f %x in ('dir /ad /b') do del %x\%xipad\*thumb.png
for /f %x in ('dir /ad /b') do del %x\%xipad\*thumb.jpg
for /f %x in ('dir /ad /b') do del %x\xml.php
for /f %x in ('dir /ad /b') do del %x\%xipad\xml.php
It looks like I can put all of my commands into a single "for /f %x in..." loop and then do the logic inside. I should probably check if the extension is .png or .jpg (not with two separate commands). What's the best way to do these two actions? In addition is there something else I should implement to make this better?
PowerShell looks a little more verbose in this instance, but here's an example anyway. Again, as I mentioned in my comment - if you're trying to learn a scripting language for Windows right now, do yourself a favor and learn PowerShell!
#Get the directories we're going to work with:
Get-ChildItem -Path d:\rootdirectory\ | ? {$_.PSIsContainer} | % {
#Remove all xml.php files from current directory and current directory ipad.
Remove-Item ($_.FullName + "\xml.php")
#For all the files in the directory move the each "ipad" directory into the directory with the same name.
If ($_.Name -like *ipad) {
#Delete all png and jpg images with "thumb" in the name from each current directories ipad directory
Get-ChildItem $_ -filter "*thumb* | ? {($_.Extension -eq "jpg") -or ($_.Extension -eq "png")} | % {
Remove-Item $_
}
#...Then actually move the item
Move-Item $_ -Destination $_.FullName.Replace("ipad","")}
}
#Use else to work on the remainder of the directories:
else {
#Create a directory called "thumbs" inside all of the current directories
$thumbDir = New-Item -ItemType Directory -Path ($_.FullName + "\thumbs\")
#Move all png and jpg files in the current directory with "thumb" in the name into the "thumbs" directory.
Get-ChildItem $_ -filter "*thumb* | ? {($_.Extension -eq "jpg") -or ($_.Extension -eq "png")} | % {
Move-Item $_ -Destination $thumbDir.FullName
}
}
Just do a single for loop the following way:
for /D %%x in (*) do (
move %%xipad %%x\
md %%x\thumbs
move %%x\*thumb.png %x\thumbs\
move %%x\*thumb.jpg %x\thumbs\
del %%x\%%xipad\*thumb.png
del %%x\%%xipad\*thumb.jpg
del %%x\xml.php
del %%x\%%xipad\xml.php
)
Note that you must use a double-% in batch files for those variables. And as you notice you don't need to loop over dir output because for can iterate over files and directories on its own just fine.
As for checking the extension I'm a little at a loss what extension you want to check, specifically. You're iterating over folders but extensions on folders rarely have any significance.

How to grab the names of all sub-folders in a batch script?

I just want to know how can I get all the names of the folders in a current directory. For example in my current directory I have three folders:
stackoverflow
reddit
codinghorror
Then when I execute my batch script all the three folders will print in the screen.
How can I achieve this?
Using batch files:
for /d %%d in (*.*) do echo %%d
If you want to test that on the command line, use only one % sign in both cases.
On Windows, you can use:
dir /ad /b
/ad will get you the directories only
/b will present it in 'bare' format
EDIT (reply to comment):
If you want to iterate over these directories and do something with them, use a for command:
for /F "delims=" %%a in ('dir /ad /b') do (
echo %%a
)
note the double % - this is for use in a batch, if you use for on the command line, use a single %.
added the resetting of default space delims in response to #Helen's comment
With PowerShell:
gci | ? { $_.PSIsContainer }
Old Answer:
With PowerShell:
gci | ? {$_.Length -eq $null } | % { $_.Name }
You can use the result as an array in a script, and then foreach trough it, or whatever you want to do...
For getting all the subfolders of a specific directory and display it in CMD :
#echo off
dir C:\input /s /b /o:n /a:d
Pause&Exit
For getting all the subfolders of a specific directory and save it in a text file :
dir C:\your_directory /s /b /o:n /a:d > output.txt

Resources