Forfiles, move files that were created in [*Month] - windows

I have a problem with forfiles syntax. I want to write a simple forfiles command, that will:
Select files, that were modified in January,February,March, etc.
Move these files to another folder.
but I'm having problems to write proper syntax. Here is what I wrote at this point.
forfiles /m *.file /d (What do I write here?) /C "cmd /c move #file C:\Users\User1\Desktop\New folder"
Date modified format is: DD/MM/YYYY.

I don't think what you want is possible with forfiles unless you can process the list of months in reverse order (first move files with /d +07/08/2016, then with /d +01/07/2016, then /d +01/06/2016, and so on).
If PowerShell is an option you may have better luck using that, e.g. like this:
Get-ChildItem *.file |
Where-Object { $_.LastWriteTime.Month -eq 8 } |
Move-Item -Destination 'C:\Users\User1\Desktop\New folder'

To filter out all files modified in a certain month (June 2016 in the following example), you could use two nested forfiles loops, where the outer one passes all files modified on or after the first day of the month to the inner one, which returns all items out of them that are modified on or before the last day of the month:
> nul 2>&1 forfiles /D +01/06/2016 /C "forfiles forfiles /M #file /D -30/06/2016 /C 0x22cmd /C if #isdir==FALSE > con echo #fdate0x09#ftime0x09#path0x22"
This script returns a list of matching files with their modification dates and times. To move the files to another directory (for instance, C:\Backup\June-2016), the command line looks like this:
> nul 2>&1 forfiles /D +01/06/2016 /C "forfiles forfiles /M #file /D -30/06/2016 /C 0x22cmd /C if #isdir==FALSE move 00x7822#path00x7822 00x7822C:\Backup\June2016\\#file00x78220x22"
The redirections avoid empty lines and error messages to be output by forfiles.

Related

How to delete files end with a substring and older than N days

I want to delete extensionless files older than 7 days whose names end with _C.
Example files:
B_C_A1_C
B_C_A2_C
B_C_A3_A
test.txt
My code:
SET mypath=%cd%\downloads
ForFiles /p %mypath% /d -7 /c "cmd /c del /q %mypath%\*_C
When I execute the code, it deletes all files which contains _C, but I want to delete only files which end with _C and are older than 7 days.
How can I fix this?
For more information about the forfiles documention, see Batch file to delete files older than N days.
The wildcard expression *_C selects any files which end with _C, regardless of whether it has an extension.
The final code is insanely complicated:
forfiles /p "%cd%" /m *_C /C "cmd /c \"echo #file^|find \".\" ^|^| del #path\""
Using *_C will select the following:
anything without periods_C
It will NOT select the following:
any.thing_C
anything.txt._C
anything containing periods_C

How to rename text files within subfolders or zip files

I have multiple zip folders with unique names but the files within the folders all have the same name. I need to rename the text files to match the folder names. I also need those renamed text files to be moved to the working directory.
For example, I have the following:
name1.zip decompresses to name1\AncestryDNA.txt but need to be name1.txt.
name2.zip decompresses to name2\AncestryDNA.txt but need to be name2.txt.
I used 7-Zip 19.00 to unzip the files. I decompressed the files because I also need to remove lines starting with "#" from each decompressed text file for use in another program.
I start with a windows batch file the runs the following on my Data directory that contains my zip files:
echo Unzipping the files...
forfiles /p Data /m *.zip /c "cmd /c 7z x *.zip -o* -y"
echo Moving zip files to storage...
forfiles /p Data /m *.zip /c "cmd /c move #file ..\StorageZipFiles"
echo Trimming all except header from AncestryDNA text files...
forfiles /p Data /s /m *.txt /c "cmd /c sed -i '/#/d' #file"
These work but I can't get the rename function to work.
I tried to rename the files before decompressing...
forfiles /p Data /s /m *.zip /c "cmd /c 7z rn #file #fname\AncestryDNA.txt #fname\#fname.txt"
and...
forfiles /p Data /s /m *.zip /c "cmd /c 7z a rn #file #fname\AncestryDNA.txt #fname\#fname.txt"
and after decompressing...
forfiles /p Data /s /m *.txt /c "cmd /c ren #file #fname.txt"
but I have not been successful with carrying the name of the folder over to the text file within the folder.
When trying to rename the files after decompressing, the command prompt does not produce an error message. It keeps the old file name of AncestryDNA.txt nested within the folders name1, name2, etc.
Another way of renaming the files after decompression is this powershell script.
Get-ChildItem -recurse -path Data *.txt | rename-item -path {$_.fullname} -newname {$($_ | split-path | split-path -leaf ) + ".txt"} -whatif
This has two interleaved powershell pipelines, one gets all the right directories and the second pipeline extracts the name of the folder used to rename the file.
Note that I put a -whatif at the end of this for safety. If the output looks good then remove the -whatif to actually change the filenames. It is still best to test this on test data before using on real data.

Trouble moving files in PowerShell using forfiles to a folder whose name has more than one word

I'm new to PowerShell, and am trying to move a few excel spreadsheets into a folder titled "old folder" using the forfiles command. PowerShell says that the files have been moved, but when I check the folder they're not there. They aren't in their original location either.
forfiles /P C:\Users\NewUser\Desktop /M *.xlsx /D +27/05/2019 /C 'cmd /c move #file C:\Users\NewUser\Desktop\"old folder"\'
I tried changing the folder name to a single word "oldfolder" and it worked just fine. What am I doing wrong?
There seems to be a problem with the syntax of your /C parameter. As far as I can tell the argument should be enclosed in double-quotes. And because of the space in the file name that should also be enclosed in double-quotes. Quotes within quotes should be escaped with backslash.
I would suggest this:
forfiles /P C:\Users\NewUser\Desktop /M *.xlsx /D +27/05/2019 /C "cmd /c move #file \"C:\Users\NewUser\Desktop\old folder\""
As forfiles has it's idiosyncrasies even in cmd, I wouldn't drag that along to PowerShell.
IIUR that translates to:
Get-ChildItem 'C:\Users\NewUser\Desktop\*.xlsx' -File |
Where-Object LastWriteTime -ge [DateTime]::Today |
Move-Item -Destination 'C:\Users\NewUser\Desktop\old folder\'
Not sure if you meant that to be /D -27/05/2019 => -lt or -le instead of -ge

Batch to move folders that are 30 days old using FORFILES

I am currently working that moves ONLY folders from one directory to a folder. The current bacth file I have created is as follows.
Set /p target=Select Target Destination:
ForFiles /P "C:\Batch test" /D -4 /C "CMD /C if #ISDIR==TRUE echo Move #FILE %target%" &Move #File %target%
pause
The problem I have is with using a target directory that has a space in it for instance "C:\Move Test". I was wondering if there was a way to still move folders to another directory that has a space in the name.
You can replace the double quotes with their hexadecimal equivalent 0x22:
ForFiles /P "C:\Batch test" /D -4 /C "CMD /C if #ISDIR==TRUE (echo Move #FILE 0x22%target%0x22 & Move #File 0x22%target%0x22)"
If you get problems with other characters you can also replace them; 0x26=&, 0x28=(, 0x29=).
Your command line looks quite strange, there are several mistakes:
ForFiles /P "C:\Batch test" /D -4 /C "CMD /C if #ISDIR==TRUE echo Move #FILE %target%" &Move #File %target%
What is wrong:
you are talking about 30 days of age, but you specify /D -4, although /D -30 was correct; note that /D checks for the last modification date, not for the creation date!
there is an echo in front of the (first) move command, so the move command is displayed rather than executed; to avoid that, simply remove echo;
there is a second move command after forfiles, as it appears behind the closing quotation mark of the forfiles /C part, and behind the commmand concatenation operator &; this is completely out of scope of forfiles, therefore #file was treated literally; the ampersand and that orphaned move command needs to be removed;
to answer your actual question: to aviod problems with spaces (or other special characters) appearing in file/directory paths, put quotation marks around them; but: since that part appears within the command string after forfiles /C, which is already quoted, you cannot simply use "", you need to escape them; there are two options in forfiles: 1. using \", and 2. using 0x22 (according to the forfiles /? help, you can specify characters by their hexadecimal codes in the format 0xHH, the code 0x22 represents a " character); I strongly recommend option 2., because in variant 1. there still appear " characters that could impact the command interpreter cmd as it is not familiar with the \" escaping (its escape character is ^);
Thus the corrected command line looks like this:
ForFiles /P "C:\Batch test" /D -30 /C "CMD /C if #ISDIR==TRUE Move #FILE 0x22%target%0x22"
For the sake of completeness, this is how option 1. would look like:
ForFiles /P "C:\Batch test" /D -30 /C "CMD /C if #ISDIR==TRUE Move #FILE \"%target%\""
Note that you do not need to quote the source here, because #FILE (like all path-related #-style variables) expand to already quoted strings.

LIST (not delete!) directories older than X using command line

I need to get a list of directories older than 90 days from 'today's' date using windows command line so I can schedule a batch file to run these folders through a separate process.
I need to list folders and subfolders only, no files.
I have tried using 'dir' which produces the list I need:
dir /b /s /a:d /o:gen >C:\file_list.txt
But, I can't check for dates greater than X using 'dir'.
I've looked at using 'forfiles' but this won't produce the list as I need it which my dir attempt produces.
To add some more complexity, ideally I need to check the date on the files within a folder rather than the folders date properties.
Any help is greatly appreciated, thanks.
And if you try with Forfiles like that :
#echo off
set OLD=90
FORFILES /S /D -%OLD% /C "cmd /c IF #isdir == TRUE echo #path"
pause
For more information about Forfiles command

Resources