19

In Windows 7, how can I recursively touch all files in a directory (including subdirectories) in order to update the date/time stamp?

Does Windows 7 have a mechanism to accomplish this?

3
  • possible duplicate of Windows equivalent of the Linux command 'touch'? Commented Feb 28, 2011 at 18:21
  • The "accepted" answer in that link is about using .NET programming libraries to accomplish that for one file. The others were about adding a context menu to update single files. I was looking for a built in command to do it to N files recursively. The answer below worked for doing it for all files. It's not a built-in, but it works. Thanks.
    – jmq
    Commented Feb 28, 2011 at 18:38
  • It's not a duplicate of Windows version of the Unix touch command either, because this question is asking specifically for recursion. However, note that a few answers to that question have recursive forms.
    – JdeBP
    Commented Feb 28, 2011 at 19:14

10 Answers 10

19

There are several possibilities:

  • Use a port of a Unix touch command and simply combine find and touch in the Unix way. There are several choices. Oft-mentioned are GNUWin32, cygwin, and unxutils. Less well known, but in some ways better, are the tools in the SFUA utility toolkit, which run in the Subsystem for UNIX-based Applications that comes right there in the box with Windows 7 Ultimate edition and Windows Server 2008 R2. (For Windows XP, one can download and install Services for UNIX version 3.5.) This toolkit has a large number of command-line TUI tools, from mv and du, through the Korn and C shells, to perl and awk. It comes in both x86-64 and IA64 flavours as well as x86-32. The programs run in Windows' native proper POSIX environment, rather than with emulator DLLs (such as cygwin1.dll) layering things over Win32. And yes, the toolkit has touch and find, as well as some 300 others.
    All of these toolkits have the well-known disadvantage of running a separate process for every file to be touched, of course. That's not a problem with the following alternatives.

  • Use one of the many native Win32 touch commands that people have written and published. Many of them support options to perform recursion, without the necessity for a Unix find to wrap around them. (They are, after all, targeting a userbase that is looking for a touch command because it doesn't have a whole load of ported Unix commands.) One such is Stéphane Duguay's touch which as you can see has a --recursive option.

  • Get clever with the arcane mysteries of CMD. As mentioned in the other answer, COPY /B myfile+,, will update a file's last modification datestamp, using the little-known "plus" syntax of the COPY command (more on which can be found here, incidentally). This of course can be combined with FOR /R to perform the operation recursively, as hinted at in another answer here.

  • Use a replacement command interpreter and be less clever and more straightforward than CMD. JP Software's TCC/LE is one such. It adds an /S option to its COPY command, meaning that one could use COPY /S with the "plus" syntax to eliminate the need for a FOR wrapper. But that's really still making life unnecessarily difficult for oneself, considering that TCC/LE has a built in TOUCH command that directly supports an /S option.

2
  • 2
    +1, the COPY /B file+,, is the way to go, requires no extras... :-) Commented Feb 28, 2011 at 20:01
  • 4
    The Powershell way: (ls file).LastWriteTime = DateTime.now Commented Feb 28, 2011 at 20:05
7

To use only existing Windows functionality (nothing extra to install) try one of these:

forfiles /P C:\Path\To\Root /S /C "cmd /c Copy /B @path+,,"  

(recursively "touch" all files starting in the specified path)

OR

forfiles /S /C "cmd /c Copy /B @path+,,"   

(recursively "touch" all files starting in current directory)

3
  • 3
    -1 As-is these commands copy files from subfolders to the root and the result is a mess.
    – TonyG
    Commented Jun 29, 2018 at 17:33
  • 2
    +1 A little twist to fix what @TonyG said: forfiles /S /C "cmd /c Copy /B nul:+,," Commented Nov 23, 2018 at 19:45
  • does not change last modified
    – beppe9000
    Commented Sep 7, 2019 at 15:30
6

Since they are readily available, I would recommend taking advantage of the unxutils. They include the find and touch commands which will make this very easy.

After changing to the topmost directory you wish to modify:

find . -type f -exec touch {} +
1
  • if file names contains spaces, this would not work, so add some quotation marks: find . -type f -exec touch \"{}\" ;
    – AntonioK
    Commented Mar 13, 2023 at 16:13
4

I know this is probably a bit too late but nevertheless, I'll leave my answer just in case someone else needs the same thing.

John T's answer didn't work for me on Windows 7. After some research I found this utility called SKTimeStamp, which does the job perfectly.

Here's an article with more details on how it works: http://www.trickyways.com/2009/08/how-to-change-timestamp-of-a-file-in-windows-file-created-modified-and-accessed/.

Here are the steps you need to perform:

  • Install the application
  • Go to the directory where you needed to change timestamps
  • Search for * in the search box so that the explorer shows all files
  • When all the files are found, select them all, right click on them and choose Properties
  • In the dialogue choose the TimeStamps tab
  • Adjust your dates and times as needed and click on Touch

Voila! All your files have been updated! No need for any unix utils or command lines.

2

Or you could use the tools already built into Windows, once you already have a "touch" tool of some kind:

for /r %i in (C:\Path\To\Root\*) do @touch "%i"

OR

forfiles /P C:\Path\To\Root /S /C "touch @file"

(N.B.: If you're doing this from a batch file and want to use the for command, make sure to use double-percent signs for your variables. (e.g. %%i instead of %i)

2

Using PowerShell for current directory and all sub-directories:

dir -R | foreach { $_.LastWriteTime = [System.DateTime]::Now }

Or you can specify a folder right after dir.

2
  • what if I want to touch -d "one day ago" ? can i do math on the "Now" ? Commented Sep 1, 2023 at 19:33
  • nvm. i found it! now.addDays(-1) Commented Sep 1, 2023 at 19:35
1

It failed on Windows 7 for me too. I used different syntax and got it to work:

forfiles /c "cmd /c touch @file"

Note, I didn't use the recurse option.

1

Using powershell:

C:\> powershell  (ls your-file-name-here).LastWriteTime = Get-Date
2
  • This doesn't work for me: The property 'LastWriteTime' cannot be found on this object.
    – Ben N
    Commented Feb 10, 2016 at 19:45
  • It worked for me in Windows Server 2012: (ls .\backup_db_20150810.sql).LastWriteTime = Get-Date Commented Feb 11, 2016 at 21:37
0

The COPY /B myfile+,, command consumed so many resources that I had to force kill it since I couldn't even move my mouse again. There are some PowerShell commands mentioned here but none of the them are like idiomatic so here's what I recommend which works without any side effects:

PS> $Now = Get-Date; Get-ChildItem -Recurse -Force | ForEach-Object { $_.LastWriteTime = $Now }

Notice that I am here storing the result of the Get-Date call in a variable called $Now to avoid the overhead of calling the clock over and over again in a tight loop.

Notice further the usage of the -Force argument to Get-ChildItem which ensures that all hidden files are also updated. This might or might not be required in your use case.

0

In reference to John T's answer above :

I was trying to understand the difference between ending a find's exec command with a \; and a + (I had not known of the latter).

This was useful: (from here)

  • -exec command ;

    Execute command; true if 0 status is returned. All following arguments to find are taken to be arguments to the command until an argument consisting of ';' is encountered. The string '{}' is replaced by the current file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it is alone, as in some versions of find.

  • -exec command {} +

    This variant of the -exec action runs the specified command on the selected files, but the command line is built by appending each selected file name at the end; the total number of invocations of the command will be much less than the number of matched files. The command line is built in much the same way that xargs builds its command lines. Only one instance of '{}' is allowed within the command. The command is executed in the starting directory.

Consider a folder c:\myfolder containing 2 files a.txt and b.txt

  1. find . -type f -exec touch {} + is interpreted as:

    touch a.txt b.txt

    This is similar to the way xargs works

  2. whereas find . -type f -exec touch {} \; is interpreted as:

    touch a.txt
    touch b.txt
    

Thus, #1 is much faster (but also suffers from the limitation that the command following exec can have only one {} placeholder).

2
  • Great comment with good info, but not an answer to the question. Would have +1'd if this were a comment.
    – TonyG
    Commented Jun 29, 2018 at 17:37
  • 1
    :) I have no memory of making this post :) Commented Jul 2, 2018 at 8:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .