how to copy only selected folders using robocopy? - command-line

I have a directory in which there are 36 subfolders. I want to copy the last 18 folders using robocopy. How do I do that? Is there any option which I can use?

This batch file should skip 18 folders and use robocopy with each individual folder after that.
#echo off
for /f "skip=18 delims=" %%a in (' dir /a-d /b ') do (
robocopy "%%a" "target folder" switches
)

Related

Changing Multiple Filenames in multiple Folders with Batch

I have several Folder which contain from 5 to 20 Files with all different names. They get replaced every week, so the Name of each File also changes. But i Need them to have specific Names so i can upload them by using my SQL loader.
Is there a way to create a Batch file, which goes into every Folder that i specify, select all Files and changes all the names? Perfect Solution would just be a upcounting number like: file1.xml, file2.xml etc.
Since im a total newbie to Batch i searched around a bit and found following code, but it only changes the files in 1 specific Folder.
Dir *.xml | ForEach-Object -begin { $count=1 }
-process { rename-item $_ -NewName "$count.xml"; $count++ }
Update 1
I found the working code which allows me to rename the files in a Folder as i want them to be. I would just Need a code, that allows me to do this to several other Folders at the same time or automatically one after another.
#echo off & setlocal EnableDelayedExpansion
set a=1
for /f "delims=" %%i in ('dir /b *.xml') do (
ren "%%i" "!a!.xml"
set /a a+=1
)
#echo off & setlocal EnableDelayedExpansion
set a=1
rem make old name to prevent same name collision
for /D %%i in (*) do (
cd %%i
for /f "delims=" %%j in ('dir /b *.xml') do (
ren "%%j" "%%j-old.xml"
)
cd ..
)
rem rename process
for /D %%i in (*) do (
cd %%i
for /f "delims=" %%j in ('dir /b *.xml') do (
ren "%%j" "!a!.xml"
set /a a+=1
)
cd ..
)
echo Done
pause
Start .
hope it helps.
Here's a PowerShell code to do the same for several folders (sub-folders)
$path = 'Z:\'
Get-ChildItem -Path $path -Filter *.xml -Recurse | ForEach-Object -Begin {
[int]$count = '1'
} -Process {
Rename-Item -Path $_.FullName -NewName "$count.xml" -ErrorAction Stop
$count++
}

Need a script to delete certain type of files in a folder based on conditions

I am having some issues with OneNote overpopulating the drive with .onetoc2 files. I need a script or cmd command that deletes these files only if the folder that it's contained in does not have a .one file. I need this run for the entire directory.
I have a delete prompt that deletes all the files but I don't know how to get the conditional aspect of it accomplished.
DEL /S /Q c:\Folders \*.onetoc2
something like this could work in powershell
$folder
if (!(dir $folder *.one)) {
dir $folder *.onetoc2 | % {del $_.FullName -WhatIf}
}
for /f "delims=" %A in ('dir /b "c:\folder\*.onetoc2"') do if not exist "%~dpA%~nA.one" echo del "%A"
Use %%A in batch. Remove the echo statement to allow it to delete.

Moving files into sub folders based by average filesize

I need the help of you programming savants in creating a batch script or powershell script that will move and divide a group of files from one directory into 4 subdirectories based on an average total filesize. After the sort, the sub-directories should be roughly equal in terms of folder size.
Why do I need this?
I have 4 computers that I would like to utilize for encoding via FFMPEG and it would be helpful for a script to divide a folder into 4 parts (sub-directories) based on a total average size.
So lets say there are an assortment of movie files with varying different file sizes totaling to 100 GB, the script would divy the movie files and move them into 4 sub folders; each folder having around 25 GB. Doing this will allow the 4 machines to encode the sum of the data equally and efficiently.
After all that encoding I'll have 2 files, XYZ.(original Extension) and XYZ.264, A script that could compare the 2 files and delete the larger file would be extremely helpful and cut down on manual inspection.
Thank you, I hope this is possible.
#ECHO Off
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
PUSHD "%sourcedir%"
:: number of subdirectories
SET /a parts=4
:: make subdirs and initialise totalsizes
FOR /L %%a IN (1,1,%parts%) DO MD "%destdir%\sub%%a" 2>nul&SET /a $%%a=0
:: directory of sourcefiles, sort in reverse-size order
FOR /f "tokens=1*delims=" %%a IN (
'dir /b /a-d /o-s * '
) DO (
REM find smallest subdir by size-transferred-in
SET /a smallest=2000000000
FOR /L %%p IN (1,1,%parts%) DO IF !$%%p! lss !smallest! SET /a smallest=!$%%p!&SET part=%%p
REM transfer the file and count the size
ECHO(MOVE "%%a" "%destdir%\sub!part!"
REM divide by 100 as actual filelength possibly gt 2**31
SET "size=%%~za"
IF "!size:~0,-2!" equ "" (SET /a $!part!+=1) ELSE (SET /a $!part!=!size:~0,-2! + $!part!)
)
popd
GOTO :EOF
I believe the remarks should explain the method. The principle is to record the length-transferred to each subdirectory and select the least-filled as the destination for the file (processed in reverse-size order)
Since batch has a limit of 2^31, I chose to roughly divide the filesize by 100 by lopping of the last 2 digits. For files <100 bytes, I arbitrarily recorded that as 100 bytes.
You would need to change the settings of sourcedir and destdir to suit your circumstances.
The required MOVE commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(MOVE to MOVE to actually move the files. Append >nul to suppress report messages (eg. 1 file moved)
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "destdir=U:\destdir"
SET "spaces= "
FOR /f "delims=" %%a IN (
'dir /b /ad "%destdir%\*"'
) DO (
PUSHD "%destdir%\%%a"
FOR /f "delims=" %%f IN (
'dir /b /a-d "*.xyz" 2^>nul'
) DO (
IF EXIST "%%f.264" (
FOR %%k IN ("%%f.264") DO (
SET "sizexyz=%spaces%%%~zf"
SET "size264=%spaces%%%~zk"
IF "!sizexyz:~-15!" gtr "!size264:~-15!" (ECHO(DEL /F /Q "%%f") ELSE (ECHO(DEL /F /Q "%%f.264")
)
)
)
popd
)
GOTO :EOF
This second batch scans the directorynames into %%a then switches teporarily to the detination directory %destfile\%%a.
Once there, we look for .xyz files and for each one found, find the corresponding .xyz.264 file.
If that exists, then we find the sizes of the files (%%~zk or %%~zf) and append that to a long string of spaces. By comparing the last 15 characters of the result as a string, we can determine which is longer.
The required DEL commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO(DEL to DEL to actually delete the files.
If the .264 file is filename.264 instead of filename.xyz.264 then replace each "%%f.264" with "%%~nf.264" (the ~n selects the name-part only).
To manually enter a source directoryname, use
SET /p "sourcedir=Source directory "
To accept the source directoryname as a parameter, use
SET "sourcedir=%%~1"
To process all files, except .h264 files, change
FOR /f "delims=" %%f IN (
'dir /b /a-d "*.xyz" 2^>nul'
) DO (
to
FOR /f "delims=" %%f IN (
'dir /b /a-d "*.*" 2^>nul'
) DO if /i "%%~xf" neq ".h264" (
where *.* means "all files" and the extra if statement checks whether the extension to the filename %%f (%%~xf) is not equal to (neq) .h264 and the /i directs "regardless of case (case-Insensitive)"
This might seem like a simple request, but exact partitioning is actually a really hard problem.
The easiest way to approximate a somewhat fair partitioning is simply to sort all files (from biggest to smallest) and then distribute them one-by-one into n groups (a bit like if you were giving out cards for a card game):
# Define number of subgroups/partitions
$n = 4
# Create your destination folders:
$TargetFolders = 1..$n |ForEach-Object {
mkdir "C:\path\to\movies\sub$_"
}
# Find the movie files sort by length, descending
$Files = Get-ChildItem "C:\path\to\movies" -Recurse |Where-Object {'.mp4','.mpg','.xyz' -contains $_.Extension} |Sort-Object Length -Descending
for($i = 0; $i -lt $Files.Count; $i++)
{
# Move files into sub folders, using module $n to "rotate" target folder
Move-Item $Files[$i].FullName -Destination $TargetFolders[$i % $n]
}
If you have multiple file types that you want to include, use a Where-Object filter instead of the Filter parameter with Get-ChildItem:
$Files = Get-ChildItem "C:\path\to\movies" -File -Recurse |Where-Object {'.mp4','.mpg','.xyz' -contains $_.Extension} |Sort-Object Length -Descending
#!/bin/bash
nbr_of_dirs=4
# Go to directory if specified, otherwise execute in current directory
if [ -n "$1" ]; then
cd $1
fi
# Create output directories and store them in an array
for i in $(seq 1 $nbr_of_dirs); do
dir=dir_$i
mkdir $dir
dirs[i]=$dir
done
# For every non-directory, in decreasing size:
# find out the current smallest directory and move the file there
ls -pS | grep -v / | while read line; do
smallest_dir=$(du -S ${dirs[#]} | sort -n | head -1 | cut -f2)
mv "$line" $smallest_dir
done
Remember to keep the script file in a different directory when executing this. The script iterates over every file, so if the script was in the directory too it would be moved to one of the sub-directories.

Flatten Files in Subfolders on Windows 7 (cmd or PowerShell)

I have a large volume of files organized in a very hierarchical folder structure. In this structure, the file that I care about is always located in the lowest level of the folders. As such, I'd like to flatten the directory so that it's easier to access the files that I care about. However, I'd like to preserve the 2 higher levels (Person & Project) of the folder structure.
Here's an example of the EXISTING folder directory:
Directory
Tom
Project 1
Subfolder Level A
FileA
FileB
Project 2
Subfolder Level C
FileC
FileD
Jerry
Project 1
Subfolder Level E
FileE
Here's an example of the DESIRED folder directory:
Directory
Tom
Project 1
FileA
FileB
Project 2
FileC
FileD
Jerry
Project 1
FileE
I have tried doing something like this, however this flattens all of the files into a single directory:
for /r %f in (*) do #copy "%f" .
However, this produces:
Directory
FileA
FileB
FileC
FileD
FileE
I'd appreciate any guidance that you can offer. Thanks a lot!
Here is a Powershell approach. It gets a list of the folders at the level that you want. Then it moves all the sub files up to that level. it will also remove the sub folders.
$Rootfolder = Dir directory\*\* -Directory
ForEach($folder in $Rootfolder)
{
Dir $folder.fullname -Recurse -File | Copy-Item -Destination $folder.fullname
Dir $folder.fullname -Recurse -Directory | Remove-Item -Force -Recurse -WhatIf
}
If you want it to delete, remove the -WhatIf from the last line.
Throw a couple of extra for loops around the one that works then.
e.g. First change to the name folder, then the project folder, looping through both levels.
for /D %n in (*) do (
pushd %n
for /D %p in (*) do (
pushd %p
for /r %f in (*) do #copy "%f" .
popd
)
popd
)
If you put this in a bat file, remember to replace % with %%
#echo off
pushd yourDirectory
for /d %%A in (*) do for /d %%B in ("%%A\*") do for /d %%C in ("%%B\*") do (
pushd "%%C"
for /r %%F in (*) do move /y "%%F" "%%B" >nul
popd
rd /q /s "%%C"
)
popd
%%A contains something like "yourDirectory\Tom"
%%B contains something like "yourDirectory\Tom\Project 1"
%%C contains something like "yourDirectory\Tom\Project 1\subdirectory1"
%%F contains a file to move, to any depth
At first I thought I could eliminate PUSHD/POPD and use
for /r "%%C" %%F in (*) do ... THIS DOES NOT WORK
But that doesn't work - the value after /R cannot use a FOR variable or delayed expansion because of how the command is parsed.
I tweaked #ScottC's answer and used the following code:
for /D %%n in (*) do (
pushd %%n
for /D %%p in (*) do (
pushd %%p
for /r %%f in (*.ppt) do (
move "%%f" "[ROOT_PATH_THAT_I_WANT]\%%n\%%p".
)
popd
)
popd
)
I ran this solution as a .bat file, which is why I used %% instead of %.
%%n = name (aka C:\Directory\Name)
%%p = project (aka C:\Directory\Name\Project)
%%f = file to be moved (recursively drilling through the folders and moving them up to the project level)
Ultimately, I wasn't able to get #dbenham's suggestion of deleting the empty folders to work, so I ended up using this utility: http://www.jonasjohn.de/red.htm. So far it seems pretty intuitive and like it's taking care of the problem without much effort from me :)
Thanks for the help everybody!

Command to find all view private files in the current directory recursively

What is the clearcase Command to find all view private files in the current directory recursively?
The usual commands are based on cleartool ls:
ct lsprivate: but it is only for dynamic views, not snapshot views
ct ls -rec -view_only: at least, it works in both snapshot and dynamic views
However both list also your checked-out files.
If you want only the private files, ie skipping the hijacked/eclipsed/checked-out and symlinks, you need to filter those out.
In Windows, that would be:
for /F "usebackq delims=" %i in (`cleartool ls -rec ^| find /V "Rule:" ^| find /V "hijacked" ^| find /V "eclipsed" ^| find /V "-->"`) do #echo "%i"
In Unix:
cleartool ls -rec | grep -v "Rule:" | grep -v "hijacked" | grep -v "eclipsed" | grep -v "-->" | xargs echo
In case it helps anyone else reading this question here is VonC's windows solution with a couple of minor changes to run as a windows script:
#echo off
setlocal
for /F "usebackq delims=" %%A in (`cleartool ls -rec ^| find /V "Rule:" ^| find /V "hijacked" ^| find /V "eclipsed" ^| find /V "-->"`) do #echo "%%A"
Replace #echo with rmdir /S /Q and del /F to do the actual deletions as described here. So the final script is:
#echo off
setlocal
for /F "usebackq delims=" %%A in (`cleartool ls -rec ^| find /V "Rule:" ^| find /V "hijacked" ^| find /V "eclipsed" ^| find /V "-->"`) do rmdir /S /Q "%%A"
for /F "usebackq delims=" %%A in (`cleartool ls -rec ^| find /V "Rule:" ^| find /V "hijacked" ^| find /V "eclipsed" ^| find /V "-->"`) do del /F "%%A"
If you save as a .bat file under the element of the view you are cleaning from, the script will clean up by deleting itself as well :-)
I amended the version by #MilesHampson since this returned too many results for me and, I want to run this as a batch file.
My new files won't be in the debug or obj folder and as such, I don't need to see any results for those folders... I'm also only working on C#. So that's all I need to see.
#echo off
setlocal
#echo Searching, please wait as this can take a while...
for /F "usebackq delims=" %%A in (`cleartool ls -rec ^| find /V "Rule:" ^| find /V "hijacked" ^| find /V "eclipsed" ^| find /V "-->" ^| find /V "obj" ^| find /V "debug"`) do (
if "%%~xA"==".cs" echo %%A
)
)
#echo === === === === === Search Complete === === === === === ===
pause
Create a bat file with the above, drop it into your root project folder and run it. It will display those not in source control.
In case it helps anyone else reading this question, here is VonC's Unix solution with a couple of minor changes to run under Cygwin on Windows.
In Cygwin:
cleartool ls -rec | grep -v "Rule:" | grep -v "hijacked" | grep -v "eclipsed" | grep -v -- "-->"
The Cygwin line is similar to the Unix given by VonC, but note the double-dash on the last grep is needed (and the xargs is not needed).
ct lsprivate -other
Would also filter out checked-out files
ct lsprivate -co : list all checked-out files
ct lsprivate -do : list all derived object files
ct lsprivate -other : list all other private files
I followed all above solutions and it is great command. I had some more requirements that were not covered above so I modified script little more with below additional points
Excluded batch file from list (otherwise current batch file also coming in list)
Removed Directory from list as generally I am interested in file
Specially for java developer, excluded target folder and jar files
as they are not generally checked in
Removed .classpath, .project
and .settings folder which is specific to Eclipse (if they are same
level as project/modules)
#echo off
setlocal
#echo.
#echo Searching, please wait as this can take a while...
#echo.
for /F "usebackq delims=" %%i in (`cleartool ls -rec ^| find /V "Rule:" ^| find /V "hijacked" ^| find /V "eclipsed" ^| find /V "-->" ^| find /V ".settings" ^| find /V "jar" ^| find /V "keep" ^| find /V "target" ^| find /V ".classpath" ^| find /V ".project" ^| find /V "%~n0" `) do ( if not exist %%i\* #echo "%%i")
#echo.
#echo === === === === === Search Complete === === === === === ===
#echo.
#echo.
pause