This HOWTO describes how to programmatically obtain the timestamp of a file on a remote FTP server. This can be useful in situations where you only want to check, update or delete the newest or oldest files. I opted to create a HOWTO for this as I found a large number of requests for this kind of thing in my initial Google searches to accomplish this but no clear answers. I did eventually stumble upon a guy named Anmelden on the MSDN forums who posted a solution he used with .NET. Since PowerShell has the ability to directly use .NET libraries, I was able to retrofit his solution to apply directly within Powershell. The original post can be found here.
Now, before we jump into this, I’d like to quickly address one of the solutions that was commonly suggested in my original searches and that is to use the Windows FTP.exe command and extract the date that way. I actually got that to work except for my cases anyway, it had one significant draw back:
You’ll note that, with my FTP server at least, it by default returns dates in the format MMM DD HH:MM. You’ll note that the year is not returned at all and therefore it is not possible to do any kind of string manipulation to add the year. With that out of the way, let’s delve into a working solution, shall we?
Disclaimer: I’m not a .NET programmer and so I almost certainly have some of the terms (“classes, objects, methods, properties”) at least somewhat mixed up. So consider the explanations below from a layman’s perspective.
- Begin by creating a variable called $request that will store the details of what we want to get from our FTP server. We need to imbue it with special FTP style properties however so typecast it for the System.NetFtpWebRequest. This will allow it to inherit the .NET methods and properties of this class. Typecast a new web request by calling the method “Create” in the WebRequest class and provide the FTP URI and file name.
IMPORTANT NOTE: You MUST provide the full URI to the full path including the file you want to get the time stamp from. I fought with this for a while as I was getting login errors even though I knew the password was right. That’s because the Create Method is expecting a file and not just a server.
[System.Net.FtpWebRequest]$request = [System.Net.WebRequest]::Create(“ftp://[ftpsite]/filename.ext”)
- For the “Credentials” inherited property on the $request variable, add a Network credential object with the username and password for the FTP site you’d like to connect to
$request.Credentials=New-Object System.Net.NetworkCredential($Username,$Password)
- For the “Method” property of the $request variable, (ie “the request to execute”), note the notation here is a little unusual. We call the WebRequestMethods parent class and then the FTP child class by using the “+” notation. We then use the double colon “::” notation to call a specific method inside of this class. From what I read, the “+” method notation appears to be unique to Powershell.
$request.Method = [System.Net.WebRequestMethods+FTP]::GetDateTimeStamp
- Now that we have built our request, we have to send it to the server by using the GetResponse() function. This will use the ftp site, file name, username, password and command to run we specified above. The results will be saved into the $response variable
$response=$request.GetResponse()
- We now have the details, including timestamp of the file that we requested above. To get the timestamp of the file, we need to look at the property StatusDescription and save it into a temporary variable
$temp = $response.StatusDescription
- The string that is returned comes back in the format: “213 20140713132703.000” To get the date into a usable format, we need to perform some substring manipulation
- You’ll note there is a return code of 213 followed by a space and then followed by the date. We want to remove the error code at the beginning. To do that, we can use the LastIndexOf property to find the space character that occurs closest to the right of the string. We then want to return 1 character after this so we don’t include the space in our result
$temp = $temp.Substring($temp.LastIndexOf(” “) + 1)
- This leaves us with “20140713132703.000“. We now see that the date is written as YYYYMMDDHHMMSS.000. We only want the date (and not the time) in this case so we are going to extract and build the required string
- First we grab the characters in position 0 to 4 (the year), than we’ll start from position 4 (remember we start counting at 0 so this is position 5 or the month field) and take 2 characters which is the month
- Lastly we start at position 6 and pull two characters for the day . We’ll then insert dashes in between each of them to make it easier to read
$FileCreationDateTime=$temp.Substring(0, 4) + “-” + $temp.Substring(4, 2) + “-” + $temp.Substring(6, 2)
- Congratulations, you have have a variable with the time stamp of your file. It looks like this:
2014-07-13
Note that it is currently a string, so if you want to perform date math, you need to first typecast it as [DateTime]
For example, if you want to do something if the file is older than 3 days:
if ( [DateTime]$FileCreationDateTime -lt [DateTime]::Now.AddDays(-3) ) { } # Do something
Below is everything all together for easy copy and pasting:
[System.Net.FtpWebRequest]$request = [System.Net.WebRequest]::Create("ftp://[ftpsite]/filename.ext") $request.Credentials=New-Object System.Net.NetworkCredential('$Username','$Password') $request.Method = [System.Net.WebRequestMethods+FTP]::GetDateTimeStamp $response=$request.GetResponse() $temp = $response.StatusDescription $temp = $temp.Substring($temp.LastIndexOf(" ")+1) $FileCreationDateTime=$temp.Substring(0, 4) + "-" + $temp.Substring(4, 2) + "-" + $temp.Substring(6, 2) if ( [DateTime]$FileCreationDateTime -lt [DateTime]::Now.AddDays(-3) ) { } # Do something
5 comments
Skip to comment form
Robbie, thank you so much for this HOWTO. I had a very hard time searching and reading thru all the postings all over the web. Your posting is the only one that worked straight away, good job!
Hi Andi,
I’m happy to hear this post helped solve a problem for you!
– Robbie
Most systems will return the year IF IT IS DIFFERENT than the current year. Too clever by half, but pretty common.
Slightly easier solution using the LastModified property:
$ftp_site = ‘10.10.100.10’
$ftp_port = ’21’
$ftp_path = ‘//data’
$ftp_file = ‘filename.ext’
$ftp_user = ‘user’
$ftp_pass = ‘password’
$ftp_uri = ‘ftp://’ + $ftp_site + ‘:’ + $ftp_port + $ftp_path + ‘/’ + $ftp_file
$ftp_request = [System.Net.FTPWebRequest]::create($ftp_uri)
$ftp_request.Credentials = New-Object System.Net.NetworkCredential($ftp_user,$ftp_pass)
$ftp_request.Method = [System.Net.WebRequestMethods+FTP]::GetDateTimeStamp
$ftp_datetime = $ftp_request.GetResponse().LastModified
The advantage is that it creates a true date/time variable and can be manipulated accordingly:
Echo $ftp_datetime .toString(‘yyyy-MM-dd.HH.mm.ss’)
Awesome improvement Schlomey. Thanks for sharing!