I need to copy all .TXT files under a directory [subfolders included] and copy them to another directory [without subfolders] but I can't change the extension of the files after I copy them, for example to .OLD or .TXT.OLD. Is that possible to do it via .bat file? Is there any special tool to use instead?
Consider using powershell instead:
Get-ChildItem C:\path\to\root\dir -recurse | where {$_.extension -eq ".txt"} | % {Copy-Item $_.FullName -Destination C:\path\to\target\dir}
You just need to use the root part of the filename and then append your own extension in the rename. For example, to demonstrate that (you don't say you're having any issue with the logic of the actual process, just the extension manipulation, so that's what I'm addressing):
FOR %%I IN (*.txt) DO REN %%I %%~nI.txt.old
This will take all *.txt files in the current directory and rename them to the same root + extension .txt.old. There's a possible complication in that the resulting filename cannot already exist in a rename, so you may want to put it into a more complex loop such as:
FOR %%I IN (*.txt) DO (
[do other stuff here]
IF EXIST %%~nI.txt.old DEL %%~nI.txt.old
REN %%I %%~nI.txt.old
)
Try for /? at a command prompt and check out the last part of it for the syntax of filename/path substitution parameters
I am looking for a command line which can change the file extension of all the files that are under a folder and its subfolders. Is there any way to do this?
I tried with ren *.js *.txt but this only changes the file extension of the files under one folder.
I assume by ms-dos you really mean the command prompt on Windows. Not many people still use ms-dos.
The following will run your REN command on each folder within the hierarchy that contains .js files. It is probably a bit more efficient then running REN for each file individually.
for /r %F in (.) do #if exist "%F\*.js" ren "%F\*.js" "*.txt"
Double up the percents (%F becomes %%F) if run within a batch script.
You could try this:
For /R %G in (*.js) do REN "%G" "%~nG.txt"
Note that you'll need to use %% instead of % if running from a batch file.
Im trying to make a batch file that will copy all new files and folders from a source folder to an network directory. All the new subdirectories and new files should be copied (backup).
My code:
xcopy "C:\Source" "T:\Backup" /d/i/s/q
(/d for only new files, /i because source is a dir, /s for all the subdirs and files, /q just to supress the copy text)
Source contains both subdirectories and files (.txt).
The first run it copies Everything as it should. When I add a new .txt file to one of the existing subdirectories and run it again I get the message:
"An error occured when the file The directory is not empty. was being created.
The folder "T:\Backup" could not be created.
0 files copied.
(Translated from Swedish so not 100% original)
The thing is when I try this command to a local source like e.g. "C:\test" and do the same procedure it works.
Anyone who can understand why this doesn't work for the network drive?
Should I try Another command such as robocopy?
Skip xcopy and use robocopy with the /E flag instead. It's built into all recent versions of Windows. Free download for XP.
Example:
robocopy c:\source T:\backup /E
That will copy all the files in the "source" folder to the "backup" folder that haven't been copied already.
And if you don't want to have the output shown on the console (equivalent to the /Q option in xcopy):
robocopy c:\source T:\backup /E /LOG:nul
Robocopy must be better because it should create directories with the \E switch. No overwrites for files, just adds a file with extra letters or extension <> command. Still must defrag.
XCOPY "DRIVE LETTER:\windows.old\USERS" "\computername\D\NAME\" /D /E /C /R /I /K /Y /f
I need to update the "Date Modified" property of files and folders as they are copied from one location to the other so that "Date Modified" = Current System Time. I have a PC with Windows 7, and I do NOT have administrative rights on it, so I can't install any custom utilities. My current bat file uses XCOPY:
xcopy "\\sharepoint\dept\gis\Abandoned_Wire\*.*" "\\corp.dom\fs4\g1\OUTPUT\GRIDPROD\PDF\Maps\Abandon Wire Maps" /c /s /r /y /i
On my Windows XP box I use the "touch" command from UnxUtils, but I can't find an equivalent that's native to Windows 7. Thank you!
There is a very simple (though arcane) syntax to "touch" a file on Windows. (update the last modified timestamp)
If the file is in the current directory, all you need is:
copy /b fileName+
If the file is in some other path, then this works:
copy /b somePath\fileName+,, somePath\
However, it seems like you still would have a lot of coding to do, since I believe you only want to touch files that are copied.
The following is untested, though I believe it will work. I can't vouch for the performance. This solution requires 2 unused drive letters. I'm assuming K: and L: are available.
#echo off
:: map unused drive letters to your source and target paths
subst K: "\\sharepoint\dept\gis\Abandoned_Wire"
subst L: "\\corp.dom\fs4\g1\OUTPUT\GRIDPROD\PDF\Maps\Abandon Wire Maps"
:: replicate the folder hierarchy
xcopy K: L: /t
:: recursively copy and touch all files
for /r K: %%F in (*) do (
xcopy "%%F" "L:%%~pnxF" /r /y
copy /b "L:%%~pnxF"+,, "L:%%~pF"
)
:: release the temporary drive mappings
subst /d K:
subst /d L:
You could use powershell, which I believe is already installed on Windows 7 by default. Add this line to your batch file to run a powershell command that updates the timestamp on all files named Abandoned_Wire*.*:
powershell.exe -command "ls 'folder\Abandoned_Wire\*.*' | foreach-object { $_.LastWriteTime = Get-Date }"
What that line is doing is simply:
-command: tells powershell to run the following command and return immediately
ls: list all matching files at the path specified
foreach-object: run the following block on each file that ls found
$_.LastWriteTime = Get-Date: for each file, set the LastWriteTime to the value returned by Get-Date (today's date and time)
Robocopy should be able to do this for you. robocopy is a native tool included in Windows since Vista.
robocopy "\sharepoint\dept\gis\Abandoned_Wire" "\corp.dom\fs4\g1\OUTPUT\GRIDPROD\PDF\Maps\Abandon Wire Maps" /COPY:DA /S /IS
By default robocopy will copy DAT: Data, Attributes, and the Time stamps, but this can be controlled with the /COPY flag.
See robocopy /? for all the options.
for /R %i in (\*.\*) do copy %i /B+ ,,/Y
As the title says, how can I recursively copy a directory structure but only include some files. E.g given the following directory structure:
folder1
folder2
folder3
data.zip
info.txt
abc.xyz
folder4
folder5
data.zip
somefile.exe
someotherfile.dll
The files data.zip and info.txt can appear everywhere in the directory structure. How can I copy the full directory structure, but only include files named data.zip and info.txt (all other files should be ignored)?
The resulting directory structure should look like this:
copy_of_folder1
folder2
folder3
data.zip
info.txt
folder4
folder5
data.zip
You don't mention if it has to be batch only, but if you can use ROBOCOPY, try this:
ROBOCOPY C:\Source C:\Destination data.zip info.txt /E
EDIT: Changed the /S parameter to /E to include empty folders.
An alternate solution that copies one file at a time and does not require ROBOCOPY:
#echo off
setlocal enabledelayedexpansion
set "SOURCE_DIR=C:\Source"
set "DEST_DIR=C:\Destination"
set FILENAMES_TO_COPY=data.zip info.txt
for /R "%SOURCE_DIR%" %%F IN (%FILENAMES_TO_COPY%) do (
if exist "%%F" (
set FILE_DIR=%%~dpF
set FILE_INTERMEDIATE_DIR=!FILE_DIR:%SOURCE_DIR%=!
xcopy /E /I /Y "%%F" "%DEST_DIR%!FILE_INTERMEDIATE_DIR!"
)
)
The outer for statement generates any possible path combination of subdirectory in SOURCE_DIR and name in FILENAMES_TO_COPY. For each existing file xcopy is invoked. FILE_INTERMEDIATE_DIR holds the file's subdirectory path within SOURCE_DIR which needs to be created in DEST_DIR.
try piping output of find (ie. the file path) into cpio
find . -type f -name '*.jpg' | cpio -p -d -v targetdir/
cpio checks timestamp on target files -- so its safe and fast.
remove -v for faster op, once you get used to it.
If Powershell is an option, you can do this:
Copy-Item c:\sourcePath d:\destinationPath -filter data.zip -recurse
The main disadvantage is it copies all folders, even if they will end up being empty because no files match the filter you specify. So you could end up with a tree full of empty folders, in addition to the few folders that have the files you want.
To copy all text files to G: and preserve directory structure:
xcopy *.txt /s G:
Thanks To Previous Answers. :)
This script named "r4k4copy.cmd":
#echo off
for %%p in (SOURCE_DIR DEST_DIR FILENAMES_TO_COPY) do set %%p=
cls
echo :: Copy Files Including Folder Tree
echo :: http://stackoverflow.com
rem /questions/472692/how-to-copy
rem -a-directory-structure-but-only
rem -include-certain-files-using-windows
echo :: ReScripted by r4k4
echo.
if "%1"=="" goto :NoParam
if "%2"=="" goto :NoParam
if "%3"=="" goto :NoParam
setlocal enabledelayedexpansion
set SOURCE_DIR=%1
set DEST_DIR=%2
set FILENAMES_TO_COPY=%3
for /R "%SOURCE_DIR%" %%F IN (%FILENAMES_TO_COPY%) do (
if exist "%%F" (
set FILE_DIR=%%~dpF
set FILE_INTERMEDIATE_DIR=!FILE_DIR:%SOURCE_DIR%=!
xcopy /E /I /Y "%%F" "%DEST_DIR%!FILE_INTERMEDIATE_DIR!"
)
)
goto :eof
:NoParam
echo.
echo Syntax: %0 [Source_DIR] [Dest_DIR] [FileName]
echo Eg. : %0 D:\Root E:\Root\Lev1\Lev2\Lev3 *.JPG
echo Means : Copy *.JPG from D:\Root to E:\Root\Lev1\Lev2\Lev3
It accepts variable of "Source", "Destination", and "FileName".
It also can only copying specified type of files or selective filenames.
Any improvement are welcome. :)
With find and cp only:
mkdir /tmp/targetdir
cd sourcedir
find . -type f -name '*.zip' -exec cp -p --parents {} /tmp/targetdir ";"
find . -type f -name '*.txt' -exec cp -p --parents {} /tmp/targetdir ";"
Similar to Paulius' solution, but the files you don't care about are not copied then deleted:
#echo OFF
:: Replace c:\temp with the directory where folder1 resides.
cd c:\temp
:: You can make this more generic by passing in args for the source and destination folders.
for /f "usebackq" %%I in (`dir /b /s /a:-d folder1`) do #echo %%~nxI | find /V "data.zip" | find /v "info.txt" >> exclude_list.txt
xcopy folder1 copy_of_folder1 /EXCLUDE:exclude_list.txt /E /I
That's only two simple commands, but I wouldn't recommend this, unless the files that you DON'T need to copy are small. That's because this will copy ALL files and then remove the files that are not needed in the copy.
xcopy /E /I folder1 copy_of_folder1
for /F "tokens=1 delims=" %i in ('dir /B /S /A:-D copy_of_files ^| find /V "info.txt" ^| find /V "data.zip"') do del /Q "%i"
Sure, the second command is kind of long, but it works!
Also, this approach doesn't require you to download and install any third party tools (Windows 2000+ BATCH has enough commands for this).
Under Linux and other UNIX systems, using the tar command would do this easily.
$ tar cvf /tmp/full-structure.tar *data.zip *info.txt
Then you'd cwd to the target and:
$ tar xvf /tmp/full-structure.tar
Of course you could pipe the output from the first tar into the 2nd, but seeing it work in steps is easier to understand and explain. I'm missing the necessary cd /to/new/path/ in the following command - I just don't recall how to do it now. Someone else can add it, hopefully.
$ tar cvf - *data.zip *info.txt | tar xvf -
Tar (gnutar) is available on Windows too, but I'd probably use the xcopy method myself on that platform.
For those using Altap Salamander (2 panels file manager) : in the Options of the Copy popup, just specify the file names or masks. Easy.
XCOPY /S folder1\data.zip copy_of_folder1
XCOPY /S folder1\info.txt copy_of_folder1
EDIT: If you want to preserve the empty folders (which, on rereading your post, you seem to) use /E instead of /S.
Using WinRAR command line interface, you can copy the file names and/or file types to an archive. Then you can extract that archive to whatever location you like. This preserves the original file structure.
I needed to add missing album picture files to my mobile phone without having to recopy the music itself. Fortunately the directory structure was the same on my computer and mobile!
I used:
rar a -r C:\Downloads\music.rar X:\music\Folder.jpg
C:\Downloads\music.rar = Archive to be created
X:\music\ = Folder containing music files
Folder.jpg = Filename I wanted to copy
This created an archive with all the Folder.jpg files in the proper subdirectories.
This technique can be used to copy file types as well. If the files all had different names, you could choose to extract all files to a single directory. Additional command line parameters can archive multiple file types.
More information in this very helpful link http://cects.com/using-the-winrar-command-line-tools-in-windows/
I am fine with regular expressions, lazy and averse to installs, so I created a batch file that creates the directory and copies with vanilla DOS commands. Seems laborious but quicker for me than working out robocopy.
Create your list of source files with complete paths, including drive letter if nec, in a text file.
Switch on regular expressions in your text editor.
Add double quotes round each line in case of spaces - search string (.*) replace string "\1", and click replace all
Create two lines per file - one to create the directory, one to copy the file (qqq will be replaced with destination path) - search string (.*) replace string md qqq\1\nxcopy \1 qqq\1\n and click replace all
Remove the filename from the destination paths – search \\([^\\^"]+)"\n replace \\"\n
Replace in the destination path (in this example A:\src and B:\dest). Turn OFF regular expressions, search qqq"A:\src\ replace B:\dest\ and click replace all.
md will create nested directories. copy would probably behave identically to xcopy in this example. You might want to add /Y to xcopy to suppress overwrite confirms. You end up with a batch file like so:
md "B:\dest\a\b\c\"
xcopy "C:\src\a\b\c\e.xyz" "B:\dest\a\b\c\e.xyz"
repeated for every file in your original list. Tested on Win7.
To do this with drag and drop use winzip there's a dir structure preserve option. Simply create a new .zip at the directory level which will be your root and drag files in.